1 2/* 3 * $Id: cnid_last.c,v 1.5 2010-03-31 09:47:32 franklahm Exp $ 4 * 5 * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) 6 * All Rights Reserved. See COPYRIGHT. 7 * 8 */ 9 10#ifdef HAVE_CONFIG_H 11#include "config.h" 12#endif /* HAVE_CONFIG_H */ 13 14#ifdef CNID_BACKEND_LAST 15#include <stdlib.h> 16#include "cnid_last.h" 17#include <atalk/util.h> 18#include <atalk/logger.h> 19 20#include <sys/types.h> 21#include <sys/stat.h> 22#include <unistd.h> 23 24/* ------------------------ */ 25cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st, 26 const cnid_t did _U_, char *name _U_, const size_t len _U_, cnid_t hint _U_) 27{ 28 29 /* FIXME: it relies on fact, that this is never called twice for the same file/dir. */ 30 /* Propably we should look through DID tree. */ 31 32 /* 33 * First thing: DID and FNUMs are 34 * in the same space for purposes of enumerate (and several 35 * other wierd places). While we consider this Apple's bug, 36 * this is the work-around: In order to maintain constant and 37 * unique DIDs and FNUMs, we monotonically generate the DIDs 38 * during the session, and derive the FNUMs from the filesystem. 39 * Since the DIDs are small, we insure that the FNUMs are fairly 40 * large by setting thier high bits to the device number. 41 * 42 * AFS already does something very similar to this for the 43 * inode number, so we don't repeat the procedure. 44 * 45 * new algorithm: 46 * due to complaints over did's being non-persistent, 47 * here's the current hack to provide semi-persistent 48 * did's: 49 * 1) we reserve the first bit for file ids. 50 * 2) the next 7 bits are for the device. 51 * 3) the remaining 24 bits are for the inode. 52 * 53 * both the inode and device information are actually hashes 54 * that are then truncated to the requisite bit length. 55 * 56 * it should be okay to use lstat to deal with symlinks. 57 */ 58 59 struct _cnid_last_private *priv; 60 61 if (!cdb || !(cdb->_private)) 62 return CNID_INVALID; 63 64 priv = (struct _cnid_last_private *) (cdb->_private); 65 66 if (S_ISDIR(st->st_mode)) 67 return htonl(priv->last_did++); 68 else 69 return htonl((st->st_dev << 16) | (st->st_ino & 0x0000ffff)); 70} 71 72 73 74void cnid_last_close(struct _cnid_db *cdb) 75{ 76 free(cdb->volpath); 77 free(cdb->_private); 78 free(cdb); 79} 80 81 82 83int cnid_last_delete(struct _cnid_db *cdb _U_, const cnid_t id _U_) 84{ 85 return CNID_INVALID; 86} 87 88 89 90/* Return CNID for a given did/name. */ 91cnid_t cnid_last_get(struct _cnid_db *cdb _U_, const cnid_t did _U_, char *name _U_, const size_t len _U_) 92{ 93 /* FIXME: it relies on fact, that this is never called twice for the same file/dir. */ 94 /* Propably we should look through DID tree. */ 95 return CNID_INVALID; 96} 97 98 99 100/* */ 101cnid_t cnid_last_lookup(struct _cnid_db *cdb _U_, const struct stat *st _U_, const cnid_t did _U_, 102 char *name _U_, const size_t len _U_) 103{ 104 /* FIXME: this function doesn't work in [last] scheme ! */ 105 /* Should be never called or CNID should be somewhat refactored again. */ 106 return CNID_INVALID; 107} 108 109 110static struct _cnid_db *cnid_last_new(const char *volpath) 111{ 112 struct _cnid_db *cdb; 113 struct _cnid_last_private *priv; 114 115 if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) 116 return NULL; 117 118 if ((cdb->volpath = strdup(volpath)) == NULL) { 119 free(cdb); 120 return NULL; 121 } 122 123 if ((cdb->_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) { 124 free(cdb->volpath); 125 free(cdb); 126 return NULL; 127 } 128 129 /* Set up private state */ 130 priv = (struct _cnid_last_private *) (cdb->_private); 131 priv->last_did = 17; 132 133 /* Set up standard fields */ 134 cdb->flags = 0; 135 cdb->cnid_add = cnid_last_add; 136 cdb->cnid_delete = cnid_last_delete; 137 cdb->cnid_get = cnid_last_get; 138 cdb->cnid_lookup = cnid_last_lookup; 139 cdb->cnid_nextid = NULL; /* cnid_last_nextid; */ 140 cdb->cnid_resolve = cnid_last_resolve; 141 cdb->cnid_update = cnid_last_update; 142 cdb->cnid_close = cnid_last_close; 143 144 return cdb; 145} 146 147struct _cnid_db *cnid_last_open(struct cnid_open_args *args) 148{ 149 struct _cnid_db *cdb; 150 151 if (!args->dir) { 152 return NULL; 153 } 154 155 if ((cdb = cnid_last_new(args->dir)) == NULL) { 156 LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database"); 157 return NULL; 158 } 159 160 return cdb; 161} 162 163struct _cnid_module cnid_last_module = { 164 "last", 165 {NULL, NULL}, 166 cnid_last_open, 167 0 168}; 169 170/* Return the did/name pair corresponding to a CNID. */ 171char *cnid_last_resolve(struct _cnid_db *cdb _U_, cnid_t * id _U_, void *buffer _U_, size_t len _U_) 172{ 173 /* FIXME: frankly, it does not work. As get, add and other functions. */ 174 return NULL; 175} 176 177 178int cnid_last_update(struct _cnid_db *cdb _U_, const cnid_t id _U_, const struct stat *st _U_, 179 const cnid_t did _U_, char *name _U_, const size_t len _U_) 180{ 181 return 0; 182} 183 184 185#endif /* CNID_BACKEND_LAST */ 186