]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/tdb/cnid_tdb_open.c
Merge master
[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     
60     return cdb;
61 }
62
63 /* ---------------------------- */
64 struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
65 {
66     struct stat               st;
67     struct _cnid_db           *cdb;
68     struct _cnid_tdb_private *db;
69     size_t                    len;
70     char                      path[MAXPATHLEN + 1];
71     TDB_DATA                  key, data;
72     int                       hash_size = 131071;
73     int                       tdb_flags = 0;
74
75     if (!args->dir) {
76         /* note: dir and path are not used for in memory db */
77         return NULL;
78     }
79
80     if ((len = strlen(args->dir)) > (MAXPATHLEN - DBLEN - 1)) {
81         LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", args->dir);
82         return NULL;
83     }
84     
85     if ((cdb = cnid_tdb_new(args->dir)) == NULL) {
86         LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
87         return NULL;
88     }
89     
90     strcpy(path, args->dir);
91     if (path[len - 1] != '/') {
92         strcat(path, "/");
93         len++;
94     }
95  
96     strcpy(path + len, DBHOME);
97     if (!(args->flags & CNID_FLAG_MEMORY)) {
98         if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
99             LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
100             goto fail;
101         }
102     }
103     else {
104         hash_size = 0;
105         tdb_flags = TDB_INTERNAL;
106     }
107     strcat(path, "/");
108  
109     db = (struct _cnid_tdb_private *)cdb->_private;
110
111     path[len + DBHOMELEN] = '\0';
112     strcat(path, DBCNID);
113
114     db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~args->mask);
115     if (!db->tdb_cnid) {
116         LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path);
117         goto fail;
118     }
119     /* ------------- */
120     db->tdb_didname = db->tdb_cnid;
121     db->tdb_devino = db->tdb_cnid;
122
123     /* Check for version.  This way we can update the database if we need
124      * to change the format in any way. */
125     memset(&key, 0, sizeof(key));
126     memset(&data, 0, sizeof(data));
127     key.dptr = DBVERSION_KEY;
128     key.dsize = DBVERSION_KEYLEN;
129
130     data = tdb_fetch(db->tdb_didname, key);
131     if (!data.dptr) {
132         uint32_t version = htonl(DBVERSION);
133
134         data.dptr = (char *)&version;
135         data.dsize = sizeof(version);
136         if (tdb_store(db->tdb_didname, key, data, TDB_REPLACE)) {
137             LOG(log_error, logtype_default, "tdb_open: Error putting new version");
138             goto fail;
139         }
140     }
141     else {
142         free(data.dptr);
143     }
144         
145     return cdb;
146
147 fail:
148     free(cdb->_private);
149     free(cdb->volpath);
150     free(cdb);
151     
152     return NULL;
153 }
154
155 struct _cnid_module cnid_tdb_module = {
156     "tdb",
157     {NULL, NULL},
158     cnid_tdb_open,
159     CNID_FLAG_SETUID | CNID_FLAG_BLOCK
160 };
161
162
163 #endif