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 26static 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/* ---------------------------- */ 65struct _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 148fail: 149 free(cdb->_private); 150 free(cdb->volpath); 151 free(cdb); 152 153 return NULL; 154} 155 156struct _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 165