]> arthur.barton.de Git - netatalk.git/blob - libatalk/cnid/tdb/cnid_tdb_open.c
Support for using $u username variable in AFP volume definitions
[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 <atalk/volume.h>
16
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(struct vol *vol)
29 {
30     struct _cnid_db *cdb;
31
32     if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL)
33         return NULL;
34
35     cdb->cnid_db_vol = vol;
36
37     if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) {
38         free(cdb);
39         return NULL;
40     }
41
42     /* Set up standard fields */
43     cdb->cnid_db_flags = CNID_FLAG_PERSISTENT;
44
45     cdb->cnid_add = cnid_tdb_add;
46     cdb->cnid_delete = cnid_tdb_delete;
47     cdb->cnid_get = cnid_tdb_get;
48     cdb->cnid_lookup = cnid_tdb_lookup;
49     cdb->cnid_nextid = NULL;    /*cnid_tdb_nextid;*/
50     cdb->cnid_resolve = cnid_tdb_resolve;
51     cdb->cnid_update = cnid_tdb_update;
52     cdb->cnid_close = cnid_tdb_close;
53     cdb->cnid_wipe = NULL;
54
55     return cdb;
56 }
57
58 /* ---------------------------- */
59 struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
60 {
61     struct stat               st;
62     struct _cnid_db           *cdb;
63     struct _cnid_tdb_private *db;
64     size_t                    len;
65     char                      path[MAXPATHLEN + 1];
66     TDB_DATA                  key, data;
67     int                       hash_size = 131071;
68     int                       tdb_flags = 0;
69     struct vol               *vol = args->cnid_args_vol;
70
71     if ((cdb = cnid_tdb_new(vol)) == NULL) {
72         LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
73         return NULL;
74     }
75
76     if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBLEN - 1)) {
77         LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", vol->v_path);
78         return NULL;
79     }
80     
81     strcpy(path, vol->v_path);
82     if (path[len - 1] != '/') {
83         strcat(path, "/");
84         len++;
85     }
86  
87     strcpy(path + len, DBHOME);
88     if (!(args->cnid_args_flags & CNID_FLAG_MEMORY)) {
89         if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) {
90             LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
91             goto fail;
92         }
93     }
94     else {
95         hash_size = 0;
96         tdb_flags = TDB_INTERNAL;
97     }
98     strcat(path, "/");
99  
100     db = (struct _cnid_tdb_private *)cdb->cnid_db_private;
101
102     path[len + DBHOMELEN] = '\0';
103     strcat(path, DBCNID);
104
105     db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~vol->v_umask);
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 = (unsigned char *)DBVERSION_KEY;
119     key.dsize = DBVERSION_KEYLEN;
120
121     data = tdb_fetch(db->tdb_didname, key);
122     if (!data.dptr) {
123         uint32_t version = htonl(DBVERSION);
124
125         data.dptr = (unsigned 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     return cdb;
137
138 fail:
139     free(cdb->cnid_db_private);
140     free(cdb);
141     
142     return NULL;
143 }
144
145 struct _cnid_module cnid_tdb_module = {
146     "tdb",
147     {NULL, NULL},
148     cnid_tdb_open,
149     CNID_FLAG_SETUID | CNID_FLAG_BLOCK
150 };
151
152
153 #endif