2
* $Id: ofork.c,v 1.19.2.1 2003/06/09 14:53:16 srittau Exp $
4
* Copyright (c) 1996 Regents of The University of Michigan.
5
* All Rights Reserved. See COPYRIGHT.
10
#endif /* HAVE_CONFIG_H */
15
#include <sys/stat.h> /* works around a bug */
16
#include <sys/param.h>
17
#include <atalk/logger.h>
20
#include <atalk/adouble.h>
24
#include "directory.h"
27
/* we need to have a hashed list of oforks (by dev inode). just hash
29
#define OFORK_HASHSIZE 64
30
static struct ofork *ofork_table[OFORK_HASHSIZE];
32
static struct ofork **oforks = NULL;
33
static int nforks = 0;
34
static u_short lastrefnum = 0;
37
/* OR some of each character for the hash*/
38
static __inline__ unsigned long hashfn(const struct file_key *key)
43
i = ((i << 4) | (8*sizeof(i) - 4)) ^ *name++;
46
return key->inode & (OFORK_HASHSIZE - 1);
49
static __inline__ void of_hash(struct ofork *of)
53
table = &ofork_table[hashfn(&of->key)];
54
if ((of->next = *table) != NULL)
55
(*table)->prevp = &of->next;
60
static __inline__ void of_unhash(struct ofork *of)
64
of->next->prevp = of->prevp;
65
*(of->prevp) = of->next;
69
void of_pforkdesc( f )
77
for ( ofrefnum = 0; ofrefnum < nforks; ofrefnum++ ) {
78
if ( oforks[ ofrefnum ] != NULL ) {
79
fprintf( f, "%hu <%s>\n", ofrefnum, oforks[ ofrefnum ]->of_name);
84
int of_flush(const struct vol *vol)
91
for ( refnum = 0; refnum < nforks; refnum++ ) {
92
if (oforks[ refnum ] != NULL && (oforks[refnum]->of_vol == vol) &&
93
flushfork( oforks[ refnum ] ) < 0 ) {
94
LOG(log_error, logtype_afpd, "of_flush: %s", strerror(errno) );
100
int of_rename(vol, s_of, olddir, oldpath, newdir, newpath)
101
const struct vol *vol;
103
struct dir *olddir, *newdir;
104
const char *oldpath, *newpath;
106
struct ofork *of, *next, *d_ofork;
111
next = ofork_table[hashfn(&s_of->key)];
112
while ((of = next)) {
113
next = next->next; /* so we can unhash and still be all right. */
115
if (vol == of->of_vol && olddir == of->of_dir &&
116
s_of->key.dev == of->key.dev &&
117
s_of->key.inode == of->key.inode ) {
118
strncpy( of->of_name, newpath, of->of_namelen);
119
if (newdir != olddir) {
120
of->of_d_prev->of_d_next = of->of_d_next;
121
of->of_d_next->of_d_prev = of->of_d_prev;
122
if (of->of_dir->d_ofork == of) {
123
of->of_dir->d_ofork = (of == of->of_d_next) ? NULL : of->of_d_next;
126
if (!(d_ofork = newdir->d_ofork)) {
127
newdir->d_ofork = of;
128
of->of_d_next = of->of_d_prev = of;
130
of->of_d_next = d_ofork;
131
of->of_d_prev = d_ofork->of_d_prev;
132
of->of_d_prev->of_d_next = of;
133
d_ofork->of_d_prev = of;
142
#define min(a,b) ((a)<(b)?(a):(b))
145
of_alloc(vol, dir, path, ofrefnum, eid, ad, st)
154
struct ofork *of, *d_ofork;
155
u_int16_t refnum, of_refnum;
160
nforks = (getdtablesize() - 10) / 2;
161
/* protect against insane ulimit -n */
162
nforks = min(nforks, 0xffff);
163
oforks = (struct ofork **) calloc(nforks, sizeof(struct ofork *));
168
for ( refnum = ++lastrefnum, i = 0; i < nforks; i++, refnum++ ) {
169
/* cf AFP3.0.pdf, File fork page 40 */
172
if ( oforks[ refnum % nforks ] == NULL ) {
176
/* grr, Apple and their 'uniquely identifies'
177
the next line is a protection against
192
same if lastrefnum++ rather than ++lastrefnum.
196
LOG(log_error, logtype_afpd, "of_alloc: maximum number of forks exceeded.");
200
of_refnum = refnum % nforks;
201
if (( oforks[ of_refnum ] =
202
(struct ofork *)malloc( sizeof( struct ofork ))) == NULL ) {
203
LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) );
206
of = oforks[of_refnum];
208
/* see if we need to allocate space for the adouble struct */
210
ad = malloc( sizeof( struct adouble ) );
212
LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) );
216
/* initialize to zero. This is important to ensure that
217
ad_open really does reinitialize the structure. */
218
memset( ad, 0, sizeof( struct adouble ) );
220
/* Increase the refcount on this struct adouble. This is
221
decremented again in oforc_dealloc. */
230
if (!(d_ofork = dir->d_ofork)) {
232
of->of_d_next = of->of_d_prev = of;
234
of->of_d_next = d_ofork;
235
of->of_d_prev = d_ofork->of_d_prev;
236
d_ofork->of_d_prev->of_d_next = of;
237
d_ofork->of_d_prev = of;
240
/* here's the deal: we allocate enough for the standard mac file length.
241
* in the future, we'll reallocate in fairly large jumps in case
242
* of long unicode names */
243
if (( of->of_name =(char *)malloc(255 + 1)) == NULL ) {
244
LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) );
248
oforks[ of_refnum ] = NULL;
251
strncpy( of->of_name, path, of->of_namelen = 255 + 1);
253
of->of_refnum = refnum;
254
of->key.dev = st->st_dev;
255
of->key.inode = st->st_ino;
256
if (eid == ADEID_DFORK)
257
of->of_flags = AFPFORK_DATA;
259
of->of_flags = AFPFORK_RSRC;
265
struct ofork *of_find(const u_int16_t ofrefnum )
267
if (!oforks || !nforks)
270
return( oforks[ ofrefnum % nforks ] );
273
/* --------------------------
276
of_findname(const char *name, struct stat *st)
284
if (stat(name, st) < 0)
287
key.dev = st->st_dev;
288
key.inode = st->st_ino;
290
for (of = ofork_table[hashfn(&key)]; of; of = of->next) {
291
if (key.dev == of->key.dev && key.inode == of->key.inode ) {
299
void of_dealloc( of )
308
of->of_d_prev->of_d_next = of->of_d_next;
309
of->of_d_next->of_d_prev = of->of_d_prev;
310
if (of->of_dir->d_ofork == of) {
311
of->of_dir->d_ofork = (of == of->of_d_next) ? NULL : of->of_d_next;
314
oforks[ of->of_refnum % nforks ] = NULL;
317
/* decrease refcount */
318
of->of_ad->ad_refcount--;
320
if ( of->of_ad->ad_refcount <= 0) {
322
} else {/* someone's still using it. just free this user's locks */
323
ad_unlock(of->of_ad, of->of_refnum);