]> git.ipfire.org Git - people/ms/libloc.git/blob - src/lua/database.c
ee86ddad97e4bb29267765cc75bac52b971b0c99
[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, 0);
76
77 if (self->db)
78 loc_database_unref(self->db);
79
80 free(self);
81 return 0;
82 }
83
84 static int Database_lookup(lua_State* L) {
85 struct loc_network* network = NULL;
86 int r;
87
88 Database* self = luaL_checkdatabase(L, 0);
89
90 // Require a string
91 const char* address = luaL_checkstring(L, 1);
92
93 // Perform lookup
94 r = loc_database_lookup_from_string(self->db, address, &network);
95 if (r)
96 return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno));
97
98 // Create a network object
99 r = create_network(L, network);
100 loc_network_unref(network);
101
102 return r;
103 }
104
105 static const struct luaL_Reg database_functions[] = {
106 { "open", Database_open },
107 { "lookup", Database_lookup },
108 { "__gc", Database_gc },
109 { NULL, NULL },
110 };
111
112 int register_database(lua_State* L) {
113 return register_class(L, "location.Database", database_functions);
114 }