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