From: didg Date: Wed, 4 Sep 2002 17:28:08 +0000 (+0000) Subject: move of_findname key from filename to dev, inode. X-Git-Tag: point-did-cleanup~28 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=a1254e9b67206b7c1dcfe6676f3e4cf05dfe1962 move of_findname key from filename to dev, inode. --- diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 864cf26a..e3f138b7 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -1,5 +1,5 @@ /* - * $Id: desktop.c,v 1.13 2002-05-29 18:02:59 jmarcus Exp $ + * $Id: desktop.c,v 1.14 2002-09-04 17:28:08 didg Exp $ * * See COPYRIGHT. */ @@ -717,7 +717,7 @@ int ibuflen, *rbuflen; struct vol *vol; struct dir *dir; struct ofork *of; - char *path, *name; + char *path, *name, *upath; int clen; u_int32_t did; u_int16_t vid; @@ -747,13 +747,13 @@ int ibuflen, *rbuflen; clen = (u_char)*ibuf++; clen = min( clen, 199 ); - - if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) { + upath = mtoupath( vol, path ); + if ((*path == '\0') || !(of = of_findname(vol, curdir, upath, NULL))) { memset(&ad, 0, sizeof(ad)); adp = &ad; } else adp = of->of_ad; - if (ad_open( mtoupath( vol, path ), vol_noadouble(vol) | + if (ad_open( upath , vol_noadouble(vol) | (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF), O_RDWR|O_CREAT, 0666, adp) < 0 ) { return( AFPERR_ACCESS ); @@ -786,7 +786,7 @@ int ibuflen, *rbuflen; struct vol *vol; struct dir *dir; struct ofork *of; - char *path; + char *path, *upath; u_int32_t did; u_int16_t vid; @@ -809,12 +809,14 @@ int ibuflen, *rbuflen; return( AFPERR_NOOBJ ); } - if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) { + + upath = mtoupath( vol, path ); + if ((*path == '\0') || !(of = of_findname(vol, curdir, upath, NULL))) { memset(&ad, 0, sizeof(ad)); adp = &ad; } else adp = of->of_ad; - if ( ad_open( mtoupath( vol, path ), + if ( ad_open( upath, (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF), O_RDONLY, 0666, adp) < 0 ) { return( AFPERR_NOITEM ); @@ -846,7 +848,7 @@ int ibuflen, *rbuflen; struct vol *vol; struct dir *dir; struct ofork *of; - char *path; + char *path, *upath; u_int32_t did; u_int16_t vid; @@ -869,12 +871,14 @@ int ibuflen, *rbuflen; return( AFPERR_NOOBJ ); } - if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) { + upath = mtoupath( vol, path ); + if ((*path == '\0') || !(of = of_findname(vol, curdir, upath, NULL))) { memset(&ad, 0, sizeof(ad)); adp = &ad; } else adp = of->of_ad; - if ( ad_open( mtoupath( vol, path ), + + if ( ad_open( upath, (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF), O_RDWR, 0, adp) < 0 ) { switch ( errno ) { diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 6b5664a4..85ab9e9a 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1,5 +1,5 @@ /* - * $Id: file.c,v 1.53 2002-08-30 19:32:41 didg Exp $ + * $Id: file.c,v 1.54 2002-09-04 17:28:08 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -374,7 +374,7 @@ int getfilparams(struct vol *vol, #endif /* DEBUG */ upath = mtoupath(vol, path); - if ((of = of_findname(vol, dir, path))) { + if ((of = of_findname(vol, dir, upath, st))) { adp = of->of_ad; attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0); attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0); @@ -428,7 +428,7 @@ int ibuflen, *rbuflen; char *path, *upath; int creatf, did, openf, retvalue = AFP_OK; u_int16_t vid; - + int ret; #ifdef DEBUG LOG(log_info, logtype_afpd, "begin afp_createfile:"); #endif /* DEBUG */ @@ -459,13 +459,12 @@ int ibuflen, *rbuflen; } upath = mtoupath(vol, path); - { - int ret; - if (0 != (ret = check_name(vol, upath))) - return ret; - } + if (0 != (ret = check_name(vol, upath))) + return ret; - if ((of = of_findname(vol, curdir, path))) { + ret = stat(upath, &st); + /* if upath is deleted we already in trouble anyway */ + if (!ret && (of = of_findname(vol, curdir, upath, &st))) { adp = of->of_ad; } else { memset(&ad, 0, sizeof(ad)); @@ -473,11 +472,11 @@ int ibuflen, *rbuflen; } if ( creatf) { /* on a hard create, fail if file exists and is open */ - if ((stat(upath, &st) == 0) && of) + if (!ret && of) return AFPERR_BUSY; openf = O_RDWR|O_CREAT|O_TRUNC; } else { - /* on a soft create, if the file is open then ad_open won't failed + /* on a soft create, if the file is open then ad_open won't fail because open syscall is not called */ if (of) { @@ -615,7 +614,7 @@ int setfilparams(struct vol *vol, #endif /* DEBUG */ upath = mtoupath(vol, path); - if ((of = of_findname(vol, curdir, path))) { + if ((of = of_findname(vol, curdir, upath, NULL))) { adp = of->of_ad; } else { memset(&ad, 0, sizeof(ad)); @@ -892,7 +891,7 @@ int ibuflen, *rbuflen; { struct vol *vol; struct dir *dir; - char *newname, *path, *p; + char *newname, *path, *p, *upath; u_int32_t sdid, ddid; int plen, err, retvalue = AFP_OK; u_int16_t svid, dvid; @@ -933,7 +932,9 @@ int ibuflen, *rbuflen; * however, copyfile doesn't have any of that info, * and locks need to stay coherent. as a result, * we just balk if the file is opened already. */ - if (of_findname(vol, curdir, path)) + + upath = mtoupath(vol, newname ); + if (of_findname(vol, curdir, upath, NULL)) return AFPERR_DENYCONF; newname = obj->newtmp; @@ -976,7 +977,7 @@ int ibuflen, *rbuflen; } } - if ( (err = copyfile(p, mtoupath(vol, newname ), newname, + if ( (err = copyfile(p, upath, newname, vol_noadouble(vol))) < 0 ) { return err; } @@ -1641,7 +1642,8 @@ int ibuflen, *rbuflen; struct adouble add; struct adouble *adsp; struct adouble *addp; - struct ofork *opened; + struct ofork *s_of; + struct ofork *d_of; #ifdef CNID_DB int slen, dlen; @@ -1699,9 +1701,9 @@ int ibuflen, *rbuflen; } memset(&ads, 0, sizeof(ads)); adsp = &ads; - if ((opened = of_findname(vol, curdir, path))) { + if ((s_of = of_findname(vol, curdir, upath, &srcst))) { /* reuse struct adouble so it won't break locks */ - adsp = opened->of_ad; + adsp = s_of->of_ad; } /* save some stuff */ sdir = curdir; @@ -1749,10 +1751,16 @@ int ibuflen, *rbuflen; } memset(&add, 0, sizeof(add)); addp = &add; - if ((opened = of_findname(vol, curdir, path))) { + if ((d_of = of_findname(vol, curdir, upath, &destst))) { /* reuse struct adouble so it won't break locks */ - addp = opened->of_ad; + addp = d_of->of_ad; } + + /* they are not on the same device and at least one is open + */ + if ((d_of || s_of) && srcst.st_dev != destst.st_dev) + return AFPERR_MISC; + #ifdef CNID_DB /* look for destination id. */ did = cnid_lookup(vol->v_db, &destst, curdir->d_did, upath, @@ -1769,17 +1777,17 @@ int ibuflen, *rbuflen; /* now, quickly rename the file. we error if we can't. */ if ((err = renamefile(p, temp, temp, vol_noadouble(vol), adsp)) < 0) goto err_exchangefile; - of_rename(vol, sdir, spath, curdir, temp); + of_rename(vol, s_of, sdir, spath, curdir, temp); /* rename destination to source */ if ((err = renamefile(upath, p, spath, vol_noadouble(vol), addp)) < 0) goto err_src_to_tmp; - of_rename(vol, curdir, path, sdir, spath); + of_rename(vol, d_of, curdir, path, sdir, spath); /* rename temp to destination */ if ((err = renamefile(temp, upath, path, vol_noadouble(vol), adsp)) < 0) goto err_dest_to_src; - of_rename(vol, curdir, temp, curdir, path); + of_rename(vol, s_of, curdir, temp, curdir, path); #ifdef CNID_DB /* id's need switching. src -> dest and dest -> src. */ @@ -1827,17 +1835,17 @@ err_temp_to_dest: #endif /* rename dest to temp */ renamefile(upath, temp, temp, vol_noadouble(vol), adsp); - of_rename(vol, curdir, upath, curdir, temp); + of_rename(vol, s_of, curdir, upath, curdir, temp); err_dest_to_src: /* rename source back to dest */ renamefile(p, upath, path, vol_noadouble(vol), addp); - of_rename(vol, sdir, spath, curdir, path); + of_rename(vol, d_of, sdir, spath, curdir, path); err_src_to_tmp: /* rename temp back to source */ renamefile(temp, p, spath, vol_noadouble(vol), adsp); - of_rename(vol, curdir, temp, sdir, spath); + of_rename(vol, s_of, curdir, temp, sdir, spath); err_exchangefile: return err; diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index 7d690a9f..f8a61f5d 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -1,5 +1,5 @@ /* - * $Id: filedir.c,v 1.28 2002-08-29 18:57:26 didg Exp $ + * $Id: filedir.c,v 1.29 2002-09-04 17:28:08 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -384,7 +384,7 @@ int isdir; id = cnid_get(vol->v_db, sdir->d_did, p, strlen(p)); #endif /* CNID_DB */ p = ctoupath( vol, sdir, oldname ); - if ((opened = of_findname(vol, sdir, oldname))) { + if ((opened = of_findname(vol, sdir, p, NULL))) { /* reuse struct adouble so it won't break locks */ adp = opened->of_ad; } @@ -429,13 +429,12 @@ int isdir; return AFPERR_EXIST; if ( !isdir ) { - if (of_findname(vol, curdir, newname)) { + if (of_findname(vol, curdir, upath, &st)) { rc = AFPERR_EXIST; /* was AFPERR_BUSY; */ - } else if ((rc = renamefile( p, upath, newname, - vol_noadouble(vol), adp )) == AFP_OK) { - /* if it's still open, rename the ofork as well. */ - rc = of_rename(vol, sdir, oldname, curdir, newname); - + } else { + rc = renamefile( p, upath, newname,vol_noadouble(vol), adp ); + if (rc == AFP_OK) + of_rename(vol, opened, sdir, oldname, curdir, newname); } } else { rc = renamedir(p, upath, sdir, curdir, newname, vol_noadouble(vol)); @@ -580,11 +579,12 @@ int ibuflen, *rbuflen; return( AFPERR_NOOBJ ); } + upath = mtoupath(vol, path ); if ( *path == '\0' ) { rc = deletecurdir( vol, obj->oldtmp, AFPOBJ_TMPSIZ); - } else if (of_findname(vol, curdir, path)) { + } else if (of_findname(vol, curdir, upath, NULL)) { rc = AFPERR_BUSY; - } else if ((rc = deletefile( upath = mtoupath(vol, path ), 1)) == AFP_OK) { + } else if ((rc = deletefile( upath, 1)) == AFP_OK) { #ifdef CNID_DB /* get rid of entry */ cnid_t id = cnid_get(vol->v_db, curdir->d_did, upath, strlen(upath)); cnid_delete(vol->v_db, id); diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 4aaee868..28970c0a 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.34 2002-08-29 18:57:26 didg Exp $ + * $Id: fork.c,v 1.35 2002-09-04 17:28:08 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -235,7 +235,8 @@ int ibuflen, *rbuflen; u_int32_t did; u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0; char fork, *path, *upath; - u_int16_t bshort; + struct stat st; + u_int16_t bshort; ibuf++; fork = *ibuf++; @@ -281,6 +282,20 @@ int ibuflen, *rbuflen; if (check_access(upath, access ) < 0) { return AFPERR_ACCESS; } + + /* stat() data fork */ + if (stat(upath, &st) < 0) { + switch ( errno ) { + case ENOENT: + return AFPERR_NOOBJ; + case EACCES: + return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS; + default: + LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) ); + return AFPERR_PARAM; + } + } + /* XXX: this probably isn't the best way to do this. the already open bits should really be set if the fork is opened by any program, not just this one. however, that's problematic to do @@ -288,7 +303,7 @@ int ibuflen, *rbuflen; ad_open so that we can keep file locks together. FIXME: add the fork we are opening? */ - if ((opened = of_findname(vol, curdir, path))) { + if ((opened = of_findname(vol, curdir, upath, &st))) { attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0); attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0); @@ -296,38 +311,30 @@ int ibuflen, *rbuflen; } if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid, - adsame)) == NULL ) { + adsame, &st)) == NULL ) { return( AFPERR_NFILE ); } + ret = AFPERR_NOOBJ; if (access & OPENACC_WR) { /* try opening in read-write mode */ - ret = AFPERR_NOOBJ; if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) { switch ( errno ) { case EROFS: ret = AFPERR_VLOCK; case EACCES: goto openfork_err; - break; case ENOENT: - { - struct stat st; - - /* see if client asked for the data fork */ - if (fork == OPENFORK_DATA) { - if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) { - goto openfork_err; - } - adflags = ADFLAGS_DF; - - } else if (stat(upath, &st) == 0) { - /* here's the deal. we only try to create the resource - * fork if the user wants to open it for write acess. */ - if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0) - goto openfork_err; - } else + if (fork == OPENFORK_DATA) { + if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) { + goto openfork_err; + } + adflags = ADFLAGS_DF; + + /* here's the deal. we only try to create the resource + * fork if the user wants to open it for write acess. */ + if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0) goto openfork_err; } break; @@ -363,19 +370,12 @@ int ibuflen, *rbuflen; adflags = ADFLAGS_DF; break; case ENOENT: - { - struct stat st; - - /* see if client asked for the data fork */ - if (fork == OPENFORK_DATA) { - if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) { - goto openfork_err; - } - adflags = ADFLAGS_DF; - - } else if (stat(upath, &st) != 0) { + /* see if client asked for the data fork */ + if (fork == OPENFORK_DATA) { + if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) { goto openfork_err; } + adflags = ADFLAGS_DF; } break; case EMFILE : diff --git a/etc/afpd/fork.h b/etc/afpd/fork.h index 90e0ed9c..d58389f4 100644 --- a/etc/afpd/fork.h +++ b/etc/afpd/fork.h @@ -1,5 +1,5 @@ /* - * $Id: fork.h,v 1.3 2001-12-03 05:03:38 jmarcus Exp $ + * $Id: fork.h,v 1.4 2002-09-04 17:28:08 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -16,14 +16,22 @@ #include "volume.h" #include "directory.h" +struct file_key { + dev_t dev; + ino_t inode; +}; + struct ofork { struct adouble *of_ad; struct vol *of_vol; struct dir *of_dir; char *of_name; int of_namelen; + u_int16_t of_refnum; int of_flags; + + struct file_key key; struct ofork **prevp, *next; struct ofork *of_d_prev, *of_d_next; }; @@ -47,12 +55,15 @@ struct ofork { /* in ofork.c */ extern struct ofork *of_alloc __P((struct vol *, struct dir *, char *, u_int16_t *, const int, - struct adouble *)); + struct adouble *, + struct stat *)); extern void of_dealloc __P((struct ofork *)); extern struct ofork *of_find __P((const u_int16_t)); extern struct ofork *of_findname __P((const struct vol *, const struct dir *, - const char *)); + const char *, + struct stat *)); extern int of_rename __P((const struct vol *, + struct ofork *, struct dir *, const char *, struct dir *, const char *)); extern int of_flush __P((const struct vol *)); diff --git a/etc/afpd/ofork.c b/etc/afpd/ofork.c index 1f81bb9c..bbc3aa77 100644 --- a/etc/afpd/ofork.c +++ b/etc/afpd/ofork.c @@ -1,5 +1,5 @@ /* - * $Id: ofork.c,v 1.16 2002-06-17 11:40:11 didg Exp $ + * $Id: ofork.c,v 1.17 2002-09-04 17:28:08 didg Exp $ * * Copyright (c) 1996 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -24,7 +24,7 @@ #include "directory.h" #include "fork.h" -/* we need to have a hashed list of oforks (by name). just hash +/* we need to have a hashed list of oforks (by dev inode). just hash * by first letter. */ #define OFORK_HASHSIZE 64 static struct ofork *ofork_table[OFORK_HASHSIZE]; @@ -35,21 +35,22 @@ static u_short lastrefnum = 0; /* OR some of each character for the hash*/ -static __inline__ unsigned long hashfn(const char *name) +static __inline__ unsigned long hashfn(const struct file_key *key) { unsigned long i = 0; - +#if 0 while (*name) { i = ((i << 4) | (8*sizeof(i) - 4)) ^ *name++; } - return i & (OFORK_HASHSIZE - 1); +#endif + return key->inode & (OFORK_HASHSIZE - 1); } static __inline__ void of_hash(struct ofork *of) { struct ofork **table; - table = &ofork_table[hashfn(of->of_name)]; + table = &ofork_table[hashfn(&of->key)]; if ((of->next = *table) != NULL) (*table)->prevp = &of->next; *table = of; @@ -96,20 +97,24 @@ int of_flush(const struct vol *vol) return( 0 ); } - -int of_rename(vol, olddir, oldpath, newdir, newpath) +int of_rename(vol, s_of, olddir, oldpath, newdir, newpath) const struct vol *vol; +struct ofork *s_of; struct dir *olddir, *newdir; const char *oldpath, *newpath; { struct ofork *of, *next, *d_ofork; - next = ofork_table[hashfn(oldpath)]; + if (!s_of) + return AFP_OK; + + next = ofork_table[hashfn(&s_of->key)]; while ((of = next)) { next = next->next; /* so we can unhash and still be all right. */ - if ((vol == of->of_vol) && (olddir == of->of_dir) && - (strcmp(of->of_name, oldpath) == 0)) { + if (vol == of->of_vol && olddir == of->of_dir && + s_of->key.dev == of->key.dev && + s_of->key.inode == of->key.inode ) { of_unhash(of); strncpy( of->of_name, newpath, of->of_namelen); of->of_d_prev->of_d_next = of->of_d_next; @@ -137,13 +142,14 @@ const char *oldpath, *newpath; #define min(a,b) ((a)<(b)?(a):(b)) struct ofork * - of_alloc(vol, dir, path, ofrefnum, eid, ad) - struct vol *vol; -struct dir *dir; + of_alloc(vol, dir, path, ofrefnum, eid, ad, st) +struct vol *vol; +struct dir *dir; char *path; -u_int16_t *ofrefnum; -const int eid; -struct adouble *ad; +u_int16_t *ofrefnum; +const int eid; +struct adouble *ad; +struct stat *st; { struct ofork *of, *d_ofork; u_int16_t refnum, of_refnum; @@ -234,8 +240,7 @@ struct adouble *ad; /* here's the deal: we allocate enough for the standard mac file length. * in the future, we'll reallocate in fairly large jumps in case * of long unicode names */ - if (( of->of_name =(char *)malloc(255 + 1)) == - NULL ) { + if (( of->of_name =(char *)malloc(255 + 1)) == NULL ) { LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) ); if (!ad) free(of->of_ad); @@ -246,13 +251,14 @@ struct adouble *ad; strncpy( of->of_name, path, of->of_namelen = 255 + 1); *ofrefnum = refnum; of->of_refnum = refnum; - of_hash(of); - + of->key.dev = st->st_dev; + of->key.inode = st->st_ino; if (eid == ADEID_DFORK) of->of_flags = AFPFORK_DATA; else of->of_flags = AFPFORK_RSRC; + of_hash(of); return( of ); } @@ -265,29 +271,34 @@ struct ofork *of_find(const u_int16_t ofrefnum ) } /* -------------------------- - FIXME it doesn't work :-( - mac1 open file "test" with simple text - mac2 rename "test" ==> "test1" - - now of_findname return NULL - - */ struct ofork * - of_findname(const struct vol *vol, const struct dir *dir, const char *name) + of_findname(const struct vol *vol, const struct dir *dir, const char *name, + struct stat *st) { struct ofork *of; + struct file_key key; + struct stat buffer; + char *p; + + if (st == NULL) { + st = &buffer; + if (stat(name, st) < 0) + return NULL; + } + key.dev = st->st_dev; + key.inode = st->st_ino; - for (of = ofork_table[hashfn(name)]; of; of = of->next) { - if ((vol == of->of_vol) && (dir == of->of_dir) && - (strcmp(of->of_name, name) == 0)) + for (of = ofork_table[hashfn(&key)]; of; of = of->next) { + if (vol == of->of_vol && dir == of->of_dir && + key.dev == of->key.dev && key.inode == of->key.inode ) { return of; + } } return NULL; } - void of_dealloc( of ) struct ofork *of; {