]> git.ipfire.org Git - people/ms/libloc.git/blame - src/lua/database.c
lua: database: Add __close method
[people/ms/libloc.git] / src / lua / database.c
CommitLineData
7eaabd10
MT
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"
9fac2ef2 27#include "network.h"
7eaabd10
MT
28
29typedef struct database {
30 struct loc_database* db;
31} Database;
32
33static 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
42static 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
3b06229b
MT
74static int Database_close(lua_State* L) {
75 Database* self = luaL_checkdatabase(L, 1);
7eaabd10 76
3b06229b
MT
77 // Free database
78 if (self->db) {
7eaabd10 79 loc_database_unref(self->db);
3b06229b
MT
80 self->db = NULL;
81 }
82
83 return 0;
84}
85
86static int Database_gc(lua_State* L) {
87 Database* self = luaL_checkdatabase(L, 1);
7eaabd10 88
3b06229b 89 // Free the object
7eaabd10 90 free(self);
3b06229b 91
7eaabd10
MT
92 return 0;
93}
94
95static int Database_lookup(lua_State* L) {
96 struct loc_network* network = NULL;
97 int r;
98
99 Database* self = luaL_checkdatabase(L, 0);
100
101 // Require a string
102 const char* address = luaL_checkstring(L, 1);
103
104 // Perform lookup
105 r = loc_database_lookup_from_string(self->db, address, &network);
106 if (r)
107 return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno));
108
9fac2ef2
MT
109 // Create a network object
110 r = create_network(L, network);
7eaabd10
MT
111 loc_network_unref(network);
112
9fac2ef2 113 return r;
7eaabd10
MT
114}
115
116static const struct luaL_Reg database_functions[] = {
117 { "open", Database_open },
118 { "lookup", Database_lookup },
3b06229b 119 { "__close", Database_close },
e1c9275c 120 { "__gc", Database_gc },
7eaabd10
MT
121 { NULL, NULL },
122};
123
124int register_database(lua_State* L) {
e914e3ca 125 return register_class(L, "location.Database", database_functions);
7eaabd10 126}