]> git.ipfire.org Git - people/ms/libloc.git/blob - src/lua/database.c
efed6aaf9ce9d08b70d70cb4c0cc7f13621050bf
[people/ms/libloc.git] / src / lua / database.c
1 /*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2024 IPFire Development Team <info@ipfire.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15 */
16
17 #include <errno.h>
18 #include <string.h>
19
20 #include <lua.h>
21 #include <lauxlib.h>
22
23 #include <libloc/database.h>
24
25 #include "location.h"
26 #include "database.h"
27 #include "network.h"
28
29 typedef struct database {
30 struct loc_database* db;
31 } Database;
32
33 static Database* luaL_checkdatabase(lua_State* L, int i) {
34 void* userdata = luaL_checkudata(L, i, "location.Database");
35
36 // Throw an error if the argument doesn't match
37 luaL_argcheck(L, userdata, i, "Database expected");
38
39 return (Database*)userdata;
40 }
41
42 static int Database_open(lua_State* L) {
43 const char* path = NULL;
44 FILE* f = NULL;
45 int r;
46
47 // Fetch the path
48 path = luaL_checkstring(L, 1);
49
50 // Allocate a new object
51 Database* self = (Database*)lua_newuserdata(L, sizeof(*self));
52
53 // Set metatable
54 luaL_setmetatable(L, "location.Database");
55
56 // Open the database file
57 f = fopen(path, "r");
58 if (!f)
59 return luaL_error(L, "Could not open %s: %s\n", path, strerror(errno));
60
61 // Open the database
62 r = loc_database_new(ctx, &self->db, f);
63
64 // Close the file descriptor
65 fclose(f);
66
67 // Check for errors
68 if (r)
69 return luaL_error(L, "Could not open database %s: %s\n", path, strerror(errno));
70
71 return 1;
72 }
73
74 static int Database_gc(lua_State* L) {
75 Database* self = luaL_checkdatabase(L, 1);
76
77 // Free database
78 if (self->db) {
79 loc_database_unref(self->db);
80 self->db = NULL;
81 }
82
83 return 0;
84 }
85
86 static int Database_lookup(lua_State* L) {
87 struct loc_network* network = NULL;
88 int r;
89
90 Database* self = luaL_checkdatabase(L, 1);
91
92 // Require a string
93 const char* address = luaL_checkstring(L, 2);
94
95 // Perform lookup
96 r = loc_database_lookup_from_string(self->db, address, &network);
97 if (r)
98 return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno));
99
100 // Create a network object
101 r = create_network(L, network);
102 loc_network_unref(network);
103
104 return r;
105 }
106
107 static const struct luaL_Reg database_functions[] = {
108 { "open", Database_open },
109 { "lookup", Database_lookup },
110 { "__gc", Database_gc },
111 { NULL, NULL },
112 };
113
114 int register_database(lua_State* L) {
115 return register_class(L, "location.Database", database_functions);
116 }