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