]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/tdb/cnid_tdb_open.c
0aee5b4df5469ddbb3282c8d23d67f35f3bb3837
[netatalk.git] / libatalk / cnid / tdb / cnid_tdb_open.c
1 /*
2  * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
3  * All Rights Reserved. See COPYRIGHT.
4  *
5  */
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #ifdef CNID_BACKEND_TDB
11 #include <sys/param.h>   
12
13 #include "cnid_tdb.h"
14 #include <atalk/logger.h>
15 #include <stdlib.h>
16 #define DBHOME       ".AppleDB"
17 #define DBHOMELEN    9                  /* strlen(DBHOME) +1 for / */
18 #define DBLEN        12
19 #define DBCNID       "cnid2.tdb"
20
21 #define DBVERSION_KEY    "\0\0\0\0Version"
22 #define DBVERSION_KEYLEN (sizeof(DBVERSION_KEY))
23 #define DBVERSION2       0x00000002U
24 #define DBVERSION        DBVERSION2
25
26 static struct _cnid_db *cnid_tdb_new(const char *volpath)
27 {
28     struct _cnid_db *cdb;
29     struct _cnid_tdb_private *priv;
30
31     if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL)
32         return NULL;
33
34     if ((cdb->volpath = strdup(volpath)) == NULL) {
35         free(cdb);
36         return NULL;
37     }
38
39     if ((cdb->_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) {
40         free(cdb->volpath);
41         free(cdb);
42         return NULL;
43     }
44
45     /* Set up private state */
46     priv = (struct _cnid_tdb_private *) (cdb->_private);
47
48     /* Set up standard fields */
49     cdb->flags = CNID_FLAG_PERSISTENT;
50
51     cdb->cnid_add = cnid_tdb_add;
52     cdb->cnid_delete = cnid_tdb_delete;
53     cdb->cnid_get = cnid_tdb_get;
54     cdb->cnid_lookup = cnid_tdb_lookup;
55     cdb->cnid_nextid = NULL;    /*cnid_tdb_nextid;*/
56     cdb->cnid_resolve = cnid_tdb_resolve;
57     cdb->cnid_update = cnid_tdb_update;
58     cdb->cnid_close = cnid_tdb_close;
59     cdb->cnid_wipe = NULL;
60
61     return cdb;
62 }
63
64 /* ---------------------------- */
65 struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
66 {
67     struct stat               st;
68     struct _cnid_db           *cdb;
69     struct _cnid_tdb_private *db;
70     size_t                    len;
71     char                      path[MAXPATHLEN + 1];
72     TDB_DATA                  key, data;
73     int                       hash_size = 131071;
74     int                       tdb_flags = 0;
75
76     if (!args->dir) {
77         /* note: dir and path are not used for in memory db */
78         return NULL;
79     }
80
81     if ((len = strlen(args->dir)) > (MAXPATHLEN - DBLEN - 1)) {
82         LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", args->dir);
83         return NULL;
84     }
85     
86     if ((cdb = cnid_tdb_new(args->dir)) == NULL) {
87         LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
88         return NULL;
89     }
90     
91     strcpy(path, args->dir);
92     if (path[len - 1] != '/') {
93         strcat(path, "/");
94         len++;
95     }
96  
97     strcpy(path + len, DBHOME);
98     if (!(args->flags & CNID_FLAG_MEMORY)) {
99         if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
100             LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
101             goto fail;
102         }
103     }
104     else {
105         hash_size = 0;
106         tdb_flags = TDB_INTERNAL;
107     }
108     strcat(path, "/");
109  
110     db = (struct _cnid_tdb_private *)cdb->_private;
111
112     path[len + DBHOMELEN] = '\0';
113     strcat(path, DBCNID);
114
115     db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~args->mask);
116     if (!db->tdb_cnid) {
117         LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path);
118         goto fail;
119     }
120     /* ------------- */
121     db->tdb_didname = db->tdb_cnid;
122     db->tdb_devino = db->tdb_cnid;
123
124     /* Check for version.  This way we can update the database if we need
125      * to change the format in any way. */
126     memset(&key, 0, sizeof(key));
127     memset(&data, 0, sizeof(data));
128     key.dptr = (unsigned char *)DBVERSION_KEY;
129     key.dsize = DBVERSION_KEYLEN;
130
131     data = tdb_fetch(db->tdb_didname, key);
132     if (!data.dptr) {
133         uint32_t version = htonl(DBVERSION);
134
135         data.dptr = (unsigned char *)&version;
136         data.dsize = sizeof(version);
137         if (tdb_store(db->tdb_didname, key, data, TDB_REPLACE)) {
138             LOG(log_error, logtype_default, "tdb_open: Error putting new version");
139             goto fail;
140         }
141     }
142     else {
143         free(data.dptr);
144     }
145         
146     return cdb;
147
148 fail:
149     free(cdb->_private);
150     free(cdb->volpath);
151     free(cdb);
152     
153     return NULL;
154 }
155
156 struct _cnid_module cnid_tdb_module = {
157     "tdb",
158     {NULL, NULL},
159     cnid_tdb_open,
160     CNID_FLAG_SETUID | CNID_FLAG_BLOCK
161 };
162
163
164 #endif