]> git.ipfire.org Git - location/libloc.git/blob - src/lua/database.c
2912f4c94f204d25fe0fb36f68f3595d5cce3106
[location/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
28 typedef struct database {
29 struct loc_database* db;
30 } Database;
31
32 static Database* luaL_checkdatabase(lua_State* L, int i) {
33 void* userdata = luaL_checkudata(L, i, "location.Database");
34
35 // Throw an error if the argument doesn't match
36 luaL_argcheck(L, userdata, i, "Database expected");
37
38 return (Database*)userdata;
39 }
40
41 static int Database_open(lua_State* L) {
42 const char* path = NULL;
43 FILE* f = NULL;
44 int r;
45
46 // Fetch the path
47 path = luaL_checkstring(L, 1);
48
49 // Allocate a new object
50 Database* self = (Database*)lua_newuserdata(L, sizeof(*self));
51
52 // Set metatable
53 luaL_setmetatable(L, "location.Database");
54
55 // Open the database file
56 f = fopen(path, "r");
57 if (!f)
58 return luaL_error(L, "Could not open %s: %s\n", path, strerror(errno));
59
60 // Open the database
61 r = loc_database_new(ctx, &self->db, f);
62
63 // Close the file descriptor
64 fclose(f);
65
66 // Check for errors
67 if (r)
68 return luaL_error(L, "Could not open database %s: %s\n", path, strerror(errno));
69
70 return 1;
71 }
72
73 static int Database_close(lua_State* L) {
74 Database* self = luaL_checkdatabase(L, 0);
75
76 if (self->db)
77 loc_database_unref(self->db);
78
79 free(self);
80 return 0;
81 }
82
83 static int Database_lookup(lua_State* L) {
84 struct loc_network* network = NULL;
85 int r;
86
87 Database* self = luaL_checkdatabase(L, 0);
88
89 // Require a string
90 const char* address = luaL_checkstring(L, 1);
91
92 // Perform lookup
93 r = loc_database_lookup_from_string(self->db, address, &network);
94 if (r)
95 return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno));
96
97 // XXX Return the network
98
99 loc_network_unref(network);
100
101 return 0;
102 }
103
104 static const struct luaL_Reg database_functions[] = {
105 { "open", Database_open },
106 { "lookup", Database_lookup },
107 { "__gc", Database_close },
108 { NULL, NULL },
109 };
110
111 int register_database(lua_State* L) {
112 return register_class(L, "location.Database", database_functions);
113 }