]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/tdb/cnid_tdb_open.c
add a flag parameter to cnid open functions
[netatalk.git] / libatalk / cnid / tdb / cnid_tdb_open.c
1 /*
2  * $Id: cnid_tdb_open.c,v 1.6 2009-11-24 12:18:20 didg 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(const char *dir, mode_t mask, u_int32_t flags _U_)
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     
75     if (!dir) {
76         return NULL;
77     }
78
79     if ((len = strlen(dir)) > (MAXPATHLEN - DBLEN - 1)) {
80         LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", dir);
81         return NULL;
82     }
83     
84     if ((cdb = cnid_tdb_new(dir)) == NULL) {
85         LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
86         return NULL;
87     }
88     strcpy(path, dir);
89     if (path[len - 1] != '/') {
90         strcat(path, "/");
91         len++;
92     }
93  
94     strcpy(path + len, DBHOME);
95     if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~mask) < 0)) {
96         LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
97         goto fail;
98     }
99     strcat(path, "/");
100  
101     db = (struct _cnid_tdb_private *)cdb->_private;
102
103     path[len + DBHOMELEN] = '\0';
104     strcat(path, DBCNID);
105     db->tdb_cnid = tdb_open(path, 131071, 0 , O_RDWR | O_CREAT, 0666 & ~mask);
106     if (!db->tdb_cnid) {
107         LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path);
108         goto fail;
109     }
110     /* ------------- */
111     db->tdb_didname = db->tdb_cnid;
112     db->tdb_devino = db->tdb_cnid;
113
114     /* Check for version.  This way we can update the database if we need
115      * to change the format in any way. */
116     memset(&key, 0, sizeof(key));
117     memset(&data, 0, sizeof(data));
118     key.dptr = DBVERSION_KEY;
119     key.dsize = DBVERSION_KEYLEN;
120
121     data = tdb_fetch(db->tdb_didname, key);
122     if (!data.dptr) {
123         u_int32_t version = htonl(DBVERSION);
124
125         data.dptr = (char *)&version;
126         data.dsize = sizeof(version);
127         if (tdb_store(db->tdb_didname, key, data, TDB_REPLACE)) {
128             LOG(log_error, logtype_default, "tdb_open: Error putting new version");
129             goto fail;
130         }
131     }
132     else {
133         free(data.dptr);
134     }
135         
136
137     return cdb;
138
139 fail:
140     free(cdb->_private);
141     free(cdb->volpath);
142     free(cdb);
143     
144     return NULL;
145 }
146
147 struct _cnid_module cnid_tdb_module = {
148     "tdb",
149     {NULL, NULL},
150     cnid_tdb_open,
151     CNID_FLAG_SETUID | CNID_FLAG_BLOCK
152 };
153
154
155 #endif