From 94a6dde8bfdf662621e0c4df56e475ff2355bbc6 Mon Sep 17 00:00:00 2001 From: didg Date: Thu, 11 Mar 2004 02:01:59 +0000 Subject: [PATCH] add osx like resource fork. --- etc/afpd/desktop.c | 155 ++++++++++++++++---------- etc/afpd/desktop.h | 6 +- etc/afpd/directory.c | 116 ++++++++++++-------- etc/afpd/directory.h | 6 +- etc/afpd/enumerate.c | 4 +- etc/afpd/file.c | 219 +++++++++++++++++-------------------- etc/afpd/file.h | 8 +- etc/afpd/filedir.c | 14 +-- etc/afpd/fork.c | 10 +- etc/afpd/unix.c | 65 +++++++---- etc/afpd/unix.h | 10 +- etc/afpd/volume.c | 48 ++++++-- etc/afpd/volume.h | 6 +- include/atalk/adouble.h | 31 +++--- libatalk/adouble/ad_attr.c | 56 ++++++---- libatalk/adouble/ad_date.c | 10 +- libatalk/adouble/ad_open.c | 94 +++++++++++----- 17 files changed, 514 insertions(+), 344 deletions(-) diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 39b5aef2..2fa63048 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -1,5 +1,5 @@ /* - * $Id: desktop.c,v 1.26.2.4.2.9 2004-03-04 23:57:14 bfernhomberg Exp $ + * $Id: desktop.c,v 1.26.2.4.2.10 2004-03-11 02:01:59 didg Exp $ * * See COPYRIGHT. * @@ -696,45 +696,14 @@ utompath_error: return(m); } -/* ----------------------------- */ -int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +/* ------------------------- */ +static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) { - struct adouble ad, *adp; - struct vol *vol; - struct dir *dir; struct ofork *of; - struct path *path; char *name, *upath; - int clen; - u_int32_t did; - u_int16_t vid; int isadir; - - *rbuflen = 0; - ibuf += 2; - - memcpy( &vid, ibuf, sizeof( vid )); - ibuf += sizeof( vid ); - if (NULL == ( vol = getvolbyvid( vid )) ) { - return( AFPERR_PARAM ); - } - - memcpy( &did, ibuf, sizeof( did )); - ibuf += sizeof( did ); - if (NULL == ( dir = dirlookup( vol, did )) ) { - return afp_errno; - } - - if (NULL == ( path = cname( vol, dir, &ibuf )) ) { - return get_afp_errno(AFPERR_NOOBJ); - } - - if ((u_long)ibuf & 1 ) { - ibuf++; - } + int clen; + struct adouble ad, *adp; clen = (u_char)*ibuf++; clen = min( clen, 199 ); @@ -743,7 +712,7 @@ int ibuflen, *rbuflen; if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } - + isadir = path_isadir(path); if (isadir || !(of = of_findname(path))) { ad_init(&ad, vol->v_adouble); @@ -757,6 +726,11 @@ int ibuflen, *rbuflen; return( AFPERR_ACCESS ); } + if (!ad_getentryoff(adp, ADEID_COMMENT)) { + /* not defined, save nothing but return success */ + return AFP_OK; + } + if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) { if ( *path->m_name == '\0' ) { name = curdir->d_m_name; @@ -775,21 +749,18 @@ int ibuflen, *rbuflen; return( AFP_OK ); } -int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen ) +/* ----------------------------- */ +int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen ) AFPObj *obj; char *ibuf, *rbuf; int ibuflen, *rbuflen; { - struct adouble ad, *adp; struct vol *vol; struct dir *dir; - struct ofork *of; - struct path *s_path; - char *upath; - u_int32_t did; + struct path *path; + u_int32_t did; u_int16_t vid; - int isadir; - + *rbuflen = 0; ibuf += 2; @@ -805,23 +776,43 @@ int ibuflen, *rbuflen; return afp_errno; } - if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { return get_afp_errno(AFPERR_NOOBJ); } - upath = s_path->u_name; - isadir = path_isadir(s_path); - if (isadir || !(of = of_findname(s_path))) { + if ((u_long)ibuf & 1 ) { + ibuf++; + } + + return ad_addcomment(vol, path, ibuf); +} + +/* -------------------- */ +static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen) +{ + struct adouble ad, *adp; + struct ofork *of; + char *upath; + int isadir; + + + upath = path->u_name; + isadir = path_isadir(path); + if (isadir || !(of = of_findname(path))) { ad_init(&ad, vol->v_adouble); adp = &ad; } else adp = of->of_ad; + if ( ad_open( upath, ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF, O_RDONLY, 0666, adp) < 0 ) { return( AFPERR_NOITEM ); } + if (!ad_getentryoff(adp, ADEID_COMMENT)) { + return AFPERR_NOITEM; + } /* * Make sure the AD file is not bogus. */ @@ -841,21 +832,18 @@ int ibuflen, *rbuflen; return( AFP_OK ); } -int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen ) +/* -------------------- */ +int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen ) AFPObj *obj; char *ibuf, *rbuf; int ibuflen, *rbuflen; { - struct adouble ad, *adp; struct vol *vol; struct dir *dir; - struct ofork *of; struct path *s_path; - char *upath; u_int32_t did; u_int16_t vid; - int isadir; - + *rbuflen = 0; ibuf += 2; @@ -871,17 +859,28 @@ int ibuflen, *rbuflen; return afp_errno; } - if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { return get_afp_errno(AFPERR_NOOBJ); } - upath = s_path->u_name; + return ad_getcomment(vol, s_path, rbuf, rbuflen); +} + +/* ----------------------- */ +static int ad_rmvcomment(struct vol *vol, struct path *path) +{ + struct adouble ad, *adp; + struct ofork *of; + int isadir; + char *upath; + + upath = path->u_name; if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } - isadir = path_isadir(s_path); - if (isadir || !(of = of_findname(s_path))) { + isadir = path_isadir(path); + if (isadir || !(of = of_findname(path))) { ad_init(&ad, vol->v_adouble); adp = &ad; } else @@ -900,8 +899,46 @@ int ibuflen, *rbuflen; } } + if (!ad_getentryoff(adp, ADEID_COMMENT)) { + return AFP_OK; + } + ad_setentrylen( adp, ADEID_COMMENT, 0 ); ad_flush( adp, ADFLAGS_HF ); ad_close( adp, ADFLAGS_HF ); return( AFP_OK ); } + +/* ----------------------- */ +int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen ) +AFPObj *obj; +char *ibuf, *rbuf; +int ibuflen, *rbuflen; +{ + struct vol *vol; + struct dir *dir; + struct path *s_path; + u_int32_t did; + u_int16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + return get_afp_errno(AFPERR_NOOBJ); + } + + return ad_rmvcomment(vol, s_path); +} diff --git a/etc/afpd/desktop.h b/etc/afpd/desktop.h index 6e7c9c79..d753e588 100644 --- a/etc/afpd/desktop.h +++ b/etc/afpd/desktop.h @@ -1,5 +1,5 @@ /* - * $Id: desktop.h,v 1.3.6.2 2003-09-28 13:58:56 didg Exp $ + * $Id: desktop.h,v 1.3.6.3 2004-03-11 02:01:59 didg Exp $ * * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. @@ -50,10 +50,6 @@ extern char *mtoupath __P((const struct vol *, char *, cnid_t, int utf8)); extern char *utompath __P((const struct vol *, char *, cnid_t, int utf8)); extern u_char ucreator[]; -#define validupath(vol, name) ((((vol)->v_flags & AFPVOL_USEDOTS) ? \ - (strncasecmp((name),".Apple", 6) && \ - strcasecmp((name), ".Parent")) : (name)[0] != '.')) - /* FP functions */ extern int afp_opendt __P((AFPObj *, char *, int, char *, int *)); extern int afp_addcomment __P((AFPObj *, char *, int, char *, int *)); diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index b6b0797e..288df1b9 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -1,5 +1,5 @@ /* - * $Id: directory.c,v 1.71.2.4.2.10 2004-02-20 21:22:57 didg Exp $ + * $Id: directory.c,v 1.71.2.4.2.11 2004-03-11 02:01:59 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -730,7 +730,7 @@ static int deletedir(char *dir) } /* do a recursive copy. */ -static int copydir(char *src, char *dst, int noadouble) +static int copydir(const struct vol *vol, char *src, char *dst) { char spath[MAXPATHLEN + 1], dpath[MAXPATHLEN + 1]; DIR *dp; @@ -739,7 +739,6 @@ static int copydir(char *src, char *dst, int noadouble) struct utimbuf ut; size_t slen, dlen; size_t srem, drem; - int err; /* doesn't exist or the path is too long. */ @@ -785,9 +784,9 @@ static int copydir(char *src, char *dst, int noadouble) strcpy(dpath + dlen, de->d_name); if (S_ISDIR(st.st_mode)) { - if (AFP_OK != (err = copydir(spath, dpath, noadouble))) + if (AFP_OK != (err = copydir(vol, spath, dpath))) goto copydir_done; - } else if (AFP_OK != (err = copyfile(spath, dpath, NULL, noadouble))) { + } else if (AFP_OK != (err = copyfile(vol, vol, spath, dpath, NULL))) { goto copydir_done; } else { @@ -1029,6 +1028,10 @@ char **cpath; if ( movecwd( vol, dir->d_parent ) < 0 ) { return NULL; } + /* FIXME should we set, don't need to call stat() after: + ret.st_valid = 1; + ret.st_errno = EACCES; + */ ret.m_name = dir->d_m_name; ret.u_name = dir->d_u_name; ret.dir = dir; @@ -1048,6 +1051,11 @@ char **cpath; ret.u_name = path +tp; } + /* FIXME should we set : + ret.st_valid = 1; + ret.st_errno = ENOENT; + */ + dir_invalidate(vol, dir); return &ret; } @@ -1630,7 +1638,7 @@ int setdirparams(const struct vol *vol, * Check to see if a create was necessary. If it was, we'll want * to set our name, etc. */ - if ( ad_get_HF_flags( &ad ) & O_CREAT ) { + if ( (ad_get_HF_flags( &ad ) & O_CREAT) && ad_getentryoff(&ad, ADEID_NAME)) { ad_setentrylen( &ad, ADEID_NAME, strlen( curdir->d_m_name )); memcpy( ad_entry( &ad, ADEID_NAME ), curdir->d_m_name, ad_getentrylen( &ad, ADEID_NAME )); @@ -1731,7 +1739,7 @@ int setdirparams(const struct vol *vol, break; } } - if ( setdirowner( ntohl(aint), -1, vol_noadouble(vol) ) < 0 ) { + if ( setdirowner(vol, ntohl(aint), -1 ) < 0 ) { switch ( errno ) { case EPERM : case EACCES : @@ -1777,7 +1785,7 @@ int setdirparams(const struct vol *vol, } #endif /* 0 */ - if ( setdirowner( -1, ntohl(aint), vol_noadouble(vol) ) < 0 ) { + if ( setdirowner(vol, -1, ntohl(aint) ) < 0 ) { switch ( errno ) { case EPERM : case EACCES : @@ -1824,8 +1832,7 @@ int setdirparams(const struct vol *vol, } #endif /* 0 */ - if ( setdirmode( mtoumode( &ma ), vol_noadouble(vol), - (vol->v_flags & AFPVOL_DROPBOX)) < 0 ) { + if ( setdirmode( vol, mtoumode( &ma )) < 0 ) { switch ( errno ) { case EPERM : case EACCES : @@ -1882,8 +1889,7 @@ int setdirparams(const struct vol *vol, } #endif /* 0 */ - if ( setdirunixmode( aint, vol_noadouble(vol), - (vol->v_flags & AFPVOL_DROPBOX)) < 0 ) { + if ( setdirunixmode(vol, aint) < 0 ) { switch ( errno ) { case EPERM : case EACCES : @@ -2021,10 +2027,11 @@ int ibuflen, *rbuflen; return( AFPERR_ACCESS ); } - ad_setentrylen( &ad, ADEID_NAME, strlen( s_path->m_name )); - memcpy( ad_entry( &ad, ADEID_NAME ), s_path->m_name, + if (ad_getentryoff(&ad, ADEID_NAME)) { + ad_setentrylen( &ad, ADEID_NAME, strlen( s_path->m_name )); + memcpy( ad_entry( &ad, ADEID_NAME ), s_path->m_name, ad_getentrylen( &ad, ADEID_NAME )); - + } ad_setid( &ad, (vol->v_flags & AFPVOL_NODEV)?0:s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp); @@ -2044,10 +2051,10 @@ createdir_done: * newparent curdir * */ -int renamedir(src, dst, dir, newparent, newname, noadouble) +int renamedir(vol, src, dst, dir, newparent, newname) +const struct vol *vol; char *src, *dst, *newname; struct dir *dir, *newparent; -const int noadouble; { struct adouble ad; struct dir *parent; @@ -2069,7 +2076,7 @@ const int noadouble; case EXDEV: /* this needs to copy and delete. bleah. that means we have * to deal with entire directory hierarchies. */ - if ((err = copydir(src, dst, noadouble)) < 0) { + if ((err = copydir(vol, src, dst)) < 0) { deletedir(dst); return err; } @@ -2081,19 +2088,28 @@ const int noadouble; } } - ad_init(&ad, 0); /* FIXME */ + if (vol->v_adouble == AD_VERSION2_OSX) { + /* We simply move the corresponding ad file as well */ + char tempbuf[258]="._"; + rename(vol->ad_path(src,0),strcat(tempbuf,dst)); + } len = strlen( newname ); /* rename() succeeded so we need to update our tree even if we can't open * .Parent */ - if ( !ad_open( dst, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR, 0, &ad)) { - ad_setentrylen( &ad, ADEID_NAME, len ); - memcpy( ad_entry( &ad, ADEID_NAME ), newname, len ); + + ad_init(&ad, vol->v_adouble); + + if (!ad_open( dst, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR, 0, &ad)) { + if (ad_getentryoff(&ad, ADEID_NAME)) { + ad_setentrylen( &ad, ADEID_NAME, len ); + memcpy( ad_entry( &ad, ADEID_NAME ), newname, len ); + } ad_flush( &ad, ADFLAGS_HF ); ad_close( &ad, ADFLAGS_HF ); } - + if (dir->d_m_name == dir->d_u_name) dir->d_u_name = NULL; @@ -2164,33 +2180,41 @@ int pathlen; } } - /* delete stray .AppleDouble files. this happens to get .Parent files - as well. */ - if ((dp = opendir(".AppleDouble"))) { - strcpy(path, ".AppleDouble/"); - while ((de = readdir(dp))) { - /* skip this and previous directory */ - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - /* bail if the file exists in the current directory. - * note: this will not fail with dangling symlinks */ - if (stat(de->d_name, &st) == 0) { - closedir(dp); - return AFPERR_DIRNEMPT; - } + if (vol->v_adouble == AD_VERSION2_OSX) { + + if ((err = netatalk_unlink(vol->ad_path(".",0) )) ) { + return err; + } + } + else { + /* delete stray .AppleDouble files. this happens to get .Parent files + as well. */ + if ((dp = opendir(".AppleDouble"))) { + strcpy(path, ".AppleDouble/"); + while ((de = readdir(dp))) { + /* skip this and previous directory */ + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + /* bail if the file exists in the current directory. + * note: this will not fail with dangling symlinks */ + if (stat(de->d_name, &st) == 0) { + closedir(dp); + return AFPERR_DIRNEMPT; + } - strcpy(path + DOT_APPLEDOUBLE_LEN, de->d_name); - if ((err = netatalk_unlink(path))) { - closedir(dp); - return err; + strcpy(path + DOT_APPLEDOUBLE_LEN, de->d_name); + if ((err = netatalk_unlink(path))) { + closedir(dp); + return err; + } } + closedir(dp); } - closedir(dp); - } - if ( (err = netatalk_rmdir( ".AppleDouble" )) ) { - return err; + if ( (err = netatalk_rmdir( ".AppleDouble" )) ) { + return err; + } } /* now get rid of dangling symlinks */ diff --git a/etc/afpd/directory.h b/etc/afpd/directory.h index b6e7cd1b..f9113b23 100644 --- a/etc/afpd/directory.h +++ b/etc/afpd/directory.h @@ -1,5 +1,5 @@ /* - * $Id: directory.h,v 1.13.2.4 2003-07-21 05:50:54 didg Exp $ + * $Id: directory.h,v 1.13.2.4.2.1 2004-03-11 02:01:59 didg Exp $ * * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. @@ -204,8 +204,8 @@ extern void utommode __P((struct stat *, struct maccess *)); extern int getdirparams __P((const struct vol *, u_int16_t, struct path *, struct dir *, char *, int *)); extern int setdirparams __P((const struct vol *, struct path *, u_int16_t, char *)); -extern int renamedir __P((char *, char *, struct dir *, - struct dir *, char *, const int)); +extern int renamedir __P((const struct vol *, char *, char *, struct dir *, + struct dir *, char *)); extern int path_error __P((struct path *, int error)); typedef int (*dir_loop)(struct dirent *, char *, void *); diff --git a/etc/afpd/enumerate.c b/etc/afpd/enumerate.c index b7a7b376..4a6e31d7 100644 --- a/etc/afpd/enumerate.c +++ b/etc/afpd/enumerate.c @@ -1,5 +1,5 @@ /* - * $Id: enumerate.c,v 1.39.2.2.2.3 2004-02-20 21:22:58 didg Exp $ + * $Id: enumerate.c,v 1.39.2.2.2.4 2004-03-11 02:01:59 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -166,7 +166,7 @@ char *check_dirent(const struct vol *vol, char *name) if (!strcmp(name, "..") || !strcmp(name, ".")) return NULL; - if (!(validupath(vol, name))) + if (!vol->validupath(vol, name)) return NULL; /* check for vetoed filenames */ diff --git a/etc/afpd/file.c b/etc/afpd/file.c index bcb5d5bb..e4cc7a98 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1,5 +1,5 @@ /* - * $Id: file.c,v 1.92.2.2.2.17 2004-03-04 23:57:20 bfernhomberg Exp $ + * $Id: file.c,v 1.92.2.2.2.18 2004-03-11 02:02:00 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -663,9 +663,10 @@ int ibuflen, *rbuflen; } path = s_path->m_name; - ad_setentrylen( adp, ADEID_NAME, strlen( path )); - memcpy(ad_entry( adp, ADEID_NAME ), path, - ad_getentrylen( adp, ADEID_NAME )); + if (ad_getentryoff(adp, ADEID_NAME)) { + ad_setentrylen( adp, ADEID_NAME, strlen( path )); + memcpy(ad_entry( adp, ADEID_NAME ), path, ad_getentrylen( adp, ADEID_NAME )); + } ad_flush( adp, ADFLAGS_DF|ADFLAGS_HF ); ad_close( adp, ADFLAGS_DF|ADFLAGS_HF ); @@ -799,7 +800,7 @@ int setfilparams(struct vol *vol, return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS; } isad = 0; - } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) { + } else if (ad_getentryoff(adp, ADEID_NAME) && (ad_get_HF_flags( adp ) & O_CREAT) ) { ad_setentrylen( adp, ADEID_NAME, strlen( path->m_name )); memcpy(ad_entry( adp, ADEID_NAME ), path->m_name, ad_getentrylen( adp, ADEID_NAME )); @@ -876,7 +877,7 @@ int setfilparams(struct vol *vol, buf += sizeof( aint ); aint = ntohl (aint); - setfilemode(path, aint); + setfilunixmode(vol, path, aint); break; /* Client needs to set the ProDOS file info for this file. Use a defined string for TEXT to support crlf @@ -951,9 +952,9 @@ setfilparam_done: * adp adouble struct of src file, if open, or & zeroed one * */ -int renamefile(src, dst, newname, noadouble, adp ) +int renamefile(vol, src, dst, newname, adp ) +const struct vol *vol; char *src, *dst, *newname; -const int noadouble; struct adouble *adp; { char adsrc[ MAXPATHLEN + 1]; @@ -982,19 +983,19 @@ struct adouble *adp; /* FIXME warning in syslog so admin'd know there's a conflict ?*/ return AFPERR_OLOCK; /* little lie */ } - if (AFP_OK != ( rc = copyfile(src, dst, newname, noadouble )) ) { + if (AFP_OK != ( rc = copyfile(vol, vol, src, dst, newname )) ) { /* on error copyfile delete dest */ return( rc ); } - return deletefile(NULL, src, 0); + return deletefile(vol, src, 0); default : return( AFPERR_PARAM ); } } - strcpy( adsrc, ad_path( src, 0 )); + strcpy( adsrc, vol->ad_path( src, 0 )); - if (unix_rename( adsrc, ad_path( dst, 0 )) < 0 ) { + if (unix_rename( adsrc, vol->ad_path( dst, 0 )) < 0 ) { struct stat st; int err; @@ -1012,10 +1013,10 @@ struct adouble *adp; * create .AppleDouble if the file is already opened, so we * use a diff one, it's not a pb,ie it's not the same file, yet. */ - ad_init(&ad, AD_VERSION); /* FIXME */ + ad_init(&ad, vol->v_adouble); if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) { ad_close(&ad, ADFLAGS_HF); - if (!unix_rename( adsrc, ad_path( dst, 0 )) ) + if (!unix_rename( adsrc, vol->ad_path( dst, 0 )) ) err = 0; else err = errno; @@ -1046,10 +1047,12 @@ struct adouble *adp; /* don't care if we can't open the newly renamed ressource fork */ - if ( !ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) { - len = strlen( newname ); - ad_setentrylen( adp, ADEID_NAME, len ); - memcpy(ad_entry( adp, ADEID_NAME ), newname, len ); + if (!ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) { + if (ad_getentryoff(adp, ADEID_NAME) ) { + len = strlen( newname ); + ad_setentrylen( adp, ADEID_NAME, len ); + memcpy(ad_entry( adp, ADEID_NAME ), newname, len ); + } ad_flush( adp, ADFLAGS_HF ); ad_close( adp, ADFLAGS_HF ); } @@ -1114,7 +1117,7 @@ AFPObj *obj; char *ibuf, *rbuf; int ibuflen, *rbuflen; { - struct vol *vol; + struct vol *s_vol, *d_vol; struct dir *dir; char *newname, *p, *upath; struct path *s_path; @@ -1131,13 +1134,13 @@ int ibuflen, *rbuflen; memcpy(&svid, ibuf, sizeof( svid )); ibuf += sizeof( svid ); - if (NULL == ( vol = getvolbyvid( svid )) ) { + if (NULL == ( s_vol = getvolbyvid( svid )) ) { return( AFPERR_PARAM ); } memcpy(&sdid, ibuf, sizeof( sdid )); ibuf += sizeof( sdid ); - if (NULL == ( dir = dirlookup( vol, sdid )) ) { + if (NULL == ( dir = dirlookup( s_vol, sdid )) ) { return afp_errno; } @@ -1146,7 +1149,7 @@ int ibuflen, *rbuflen; memcpy(&ddid, ibuf, sizeof( ddid )); ibuf += sizeof( ddid ); - if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + if (NULL == ( s_path = cname( s_vol, dir, &ibuf )) ) { return get_afp_errno(AFPERR_PARAM); } if ( path_isadir(s_path) ) { @@ -1165,7 +1168,7 @@ int ibuflen, *rbuflen; if (of_findname(s_path)) return AFPERR_DENYCONF; - p = ctoupath( vol, curdir, newname ); + p = ctoupath( s_vol, curdir, newname ); if (!p) { return AFPERR_PARAM; @@ -1173,18 +1176,18 @@ int ibuflen, *rbuflen; #ifdef FORCE_UIDGID /* FIXME svid != dvid && dvid's user can't read svid */ #endif - if (NULL == ( vol = getvolbyvid( dvid )) ) { + if (NULL == ( d_vol = getvolbyvid( dvid )) ) { return( AFPERR_PARAM ); } - if (vol->v_flags & AFPVOL_RO) + if (d_vol->v_flags & AFPVOL_RO) return AFPERR_VLOCK; - if (NULL == ( dir = dirlookup( vol, ddid )) ) { + if (NULL == ( dir = dirlookup( d_vol, ddid )) ) { return afp_errno; } - if (( s_path = cname( vol, dir, &ibuf )) == NULL ) { + if (( s_path = cname( d_vol, dir, &ibuf )) == NULL ) { return get_afp_errno(AFPERR_NOOBJ); } if ( *s_path->m_name != '\0' ) { @@ -1201,10 +1204,10 @@ int ibuflen, *rbuflen; /* newname is always only a filename so curdir *is* its * parent folder */ - if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))) { + if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding()))) { return( AFPERR_PARAM ); } - if ( (err = copyfile(p, upath , newname, vol_noadouble(vol))) < 0 ) { + if ( (err = copyfile(s_vol, d_vol, p, upath , newname)) < 0 ) { return err; } curdir->offcnt++; @@ -1215,7 +1218,7 @@ int ibuflen, *rbuflen; } #endif /* DROPKLUDGE */ - setvoltime(obj, vol ); + setvoltime(obj, d_vol ); #ifdef DEBUG LOG(log_info, logtype_afpd, "end afp_copyfile:"); @@ -1224,7 +1227,7 @@ int ibuflen, *rbuflen; return( retvalue ); } - +/* ----------------------- */ static __inline__ int copy_all(const int dfd, const void *buf, size_t buflen) { @@ -1239,14 +1242,8 @@ static __inline__ int copy_all(const int dfd, const void *buf, switch (errno) { case EINTR: continue; - case EDQUOT: - case EFBIG: - case ENOSPC: - return AFPERR_DFULL; - case EROFS: - return AFPERR_VLOCK; default: - return AFPERR_PARAM; + return -1; } } buflen -= cc; @@ -1256,14 +1253,14 @@ static __inline__ int copy_all(const int dfd, const void *buf, LOG(log_info, logtype_afpd, "end copy_all:"); #endif /* DEBUG */ - return AFP_OK; + return 0; } /* -------------------------- */ static int copy_fd(int dfd, int sfd) { ssize_t cc; - int err = AFP_OK; + int err = 0; char filebuf[8192]; #ifdef SENDFILE_FLAVOR_LINUX @@ -1276,7 +1273,7 @@ static int copy_fd(int dfd, int sfd) while (1) { if ( offset >= st.st_size) { - return AFP_OK; + return 0; } size = (st.st_size -offset > BUF)?BUF:st.st_size -offset; if ((cc = sys_sendfile(dfd, sfd, &offset, size)) < 0) { @@ -1284,14 +1281,8 @@ static int copy_fd(int dfd, int sfd) case ENOSYS: case EINVAL: /* there's no guarantee that all fs support sendfile */ goto no_sendfile; - case EDQUOT: - case EFBIG: - case ENOSPC: - return AFPERR_DFULL; - case EROFS: - return AFPERR_VLOCK; default: - return AFPERR_PARAM; + return -1; } } } @@ -1304,12 +1295,13 @@ static int copy_fd(int dfd, int sfd) if ((cc = read(sfd, filebuf, sizeof(filebuf))) < 0) { if (errno == EINTR) continue; - err = AFPERR_PARAM; + err = -1; break; } - if (!cc || ((err = copy_all(dfd, filebuf, cc)) < 0)) + if (!cc || ((err = copy_all(dfd, filebuf, cc)) < 0)) { break; + } } return err; } @@ -1318,103 +1310,77 @@ static int copy_fd(int dfd, int sfd) * if newname is NULL (from directory.c) we don't want to copy ressource fork. * because we are doing it elsewhere. */ -int copyfile(src, dst, newname, noadouble ) +int copyfile(s_vol, d_vol, src, dst, newname ) +const struct vol *s_vol, *d_vol; char *src, *dst, *newname; -const int noadouble; { struct adouble ads, add; - int len, err = AFP_OK; + int len, err = 0; + int ret_err = 0; int adflags; + int noadouble = vol_noadouble(d_vol); struct stat st; #ifdef DEBUG LOG(log_info, logtype_afpd, "begin copyfile:"); #endif /* DEBUG */ - ad_init(&ads, 0); /* OK */ - ad_init(&add, 0); /* FIXME */ + ad_init(&ads, s_vol->v_adouble); + ad_init(&add, d_vol->v_adouble); adflags = ADFLAGS_DF; if (newname) { adflags |= ADFLAGS_HF; } if (ad_open(src , adflags | ADFLAGS_NOHF, O_RDONLY, 0, &ads) < 0) { - switch ( errno ) { - case ENOENT : - return( AFPERR_NOOBJ ); - case EACCES : - return( AFPERR_ACCESS ); - default : - return( AFPERR_PARAM ); - } + ret_err = errno; + goto done; } + if (ad_open(dst , adflags | noadouble, O_RDWR|O_CREAT|O_EXCL, 0666, &add) < 0) { + ret_err = errno; ad_close( &ads, adflags ); - if (EEXIST != (err = errno)) { - deletefile(NULL, dst, 0); - } - switch ( err ) { - case EEXIST : - return AFPERR_EXIST; - case ENOENT : - return( AFPERR_NOOBJ ); - case EACCES : - return( AFPERR_ACCESS ); - case EROFS: - return AFPERR_VLOCK; - default : - return( AFPERR_PARAM ); + if (EEXIST != ret_err) { + deletefile(d_vol, dst, 0); + goto done; } + return AFPERR_EXIST; } - if (ad_hfileno(&ads) == -1 || AFP_OK == (err = copy_fd(ad_hfileno(&add), ad_hfileno(&ads)))){ + if (ad_hfileno(&ads) == -1 || 0 == (err = copy_fd(ad_hfileno(&add), ad_hfileno(&ads)))){ /* copy the data fork */ err = copy_fd(ad_dfileno(&add), ad_dfileno(&ads)); } /* Now, reopen destination file */ - err = AFP_OK; + if (err < 0) { + ret_err = errno; + } + ad_close( &ads, adflags ); + if (ad_close( &add, adflags ) <0) { - deletefile(NULL, dst, 0); - return AFPERR_PARAM; /* FIXME */ - } else { - ad_init(&add, 0); + deletefile(d_vol, dst, 0); + ret_err = errno; + goto done; + } + else { + ad_init(&add, d_vol->v_adouble); if (ad_open(dst , adflags | noadouble, O_RDWR, 0666, &add) < 0) { - ad_close( &ads, adflags ); - deletefile(NULL, dst, 0); - switch ( err ) { - case ENOENT : - return( AFPERR_NOOBJ ); - case EACCES : - return( AFPERR_ACCESS ); - case EROFS: - return AFPERR_VLOCK; - default : - return( AFPERR_PARAM ); - } + ret_err = errno; } } - if (newname) { + if (!ret_err && newname && ad_getentryoff(&add, ADEID_NAME)) { len = strlen( newname ); ad_setentrylen( &add, ADEID_NAME, len ); memcpy(ad_entry( &add, ADEID_NAME ), newname, len ); } - ad_close( &ads, adflags ); ad_flush( &add, adflags ); if (ad_close( &add, adflags ) <0) { - err = errno; + ret_err = errno; } - if (err != AFP_OK) { - deletefile(NULL, dst, 0); - switch ( err ) { - case ENOENT : - return( AFPERR_NOOBJ ); - case EACCES : - return( AFPERR_ACCESS ); - default : - return( AFPERR_PARAM ); - } + if (ret_err) { + deletefile(d_vol, dst, 0); } /* set dest modification date to src date */ @@ -1429,7 +1395,22 @@ const int noadouble; LOG(log_info, logtype_afpd, "end copyfile:"); #endif /* DEBUG */ - return( AFP_OK ); +done: + switch ( ret_err ) { + case 0: + return AFP_OK; + case EDQUOT: + case EFBIG: + case ENOSPC: + return AFPERR_DFULL; + case ENOENT: + return AFPERR_NOOBJ; + case EACCES: + return AFPERR_ACCESS; + case EROFS: + return AFPERR_VLOCK; + } + return AFPERR_PARAM; } @@ -1444,7 +1425,7 @@ const int noadouble; WRITE lock on read only file. */ int deletefile( vol, file, checkAttrib ) -struct vol *vol; +const struct vol *vol; char *file; int checkAttrib; { @@ -1458,7 +1439,7 @@ int checkAttrib; /* try to open both forks at once */ adflags = ADFLAGS_DF|ADFLAGS_HF; while(1) { - ad_init(&ad, 0); /* OK */ + ad_init(&ad, vol->v_adouble); /* OK */ if ( ad_open( file, adflags, O_RDONLY, 0, &ad ) < 0 ) { switch (errno) { case ENOENT: @@ -1511,10 +1492,10 @@ int checkAttrib; if (ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) { err = AFPERR_BUSY; } - else if (!(err = netatalk_unlink( ad_path( file, ADFLAGS_HF)) ) && + else if (!(err = netatalk_unlink( vol->ad_path( file, ADFLAGS_HF)) ) && !(err = netatalk_unlink( file )) ) { cnid_t id; - if (vol && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)))) + if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)))) { cnid_delete(vol->v_cdb, id); } @@ -2002,17 +1983,17 @@ int ibuflen, *rbuflen; return AFPERR_MISC; /* now, quickly rename the file. we error if we can't. */ - if ((err = renamefile(p, temp, temp, vol_noadouble(vol), adsp)) < 0) + if ((err = renamefile(vol, p, temp, temp, adsp)) < 0) goto err_exchangefile; of_rename(vol, s_of, sdir, spath, curdir, temp); /* rename destination to source */ - if ((err = renamefile(upath, p, spath, vol_noadouble(vol), addp)) < 0) + if ((err = renamefile(vol, upath, p, spath, addp)) < 0) goto err_src_to_tmp; of_rename(vol, d_of, curdir, path->m_name, sdir, spath); /* rename temp to destination */ - if ((err = renamefile(temp, upath, path->m_name, vol_noadouble(vol), adsp)) < 0) + if ((err = renamefile(vol, temp, upath, path->m_name, adsp)) < 0) goto err_dest_to_src; of_rename(vol, s_of, curdir, temp, curdir, path->m_name); @@ -2053,17 +2034,17 @@ int ibuflen, *rbuflen; * properly. */ err_temp_to_dest: /* rename dest to temp */ - renamefile(upath, temp, temp, vol_noadouble(vol), adsp); + renamefile(vol, upath, temp, temp, adsp); of_rename(vol, s_of, curdir, upath, curdir, temp); err_dest_to_src: /* rename source back to dest */ - renamefile(p, upath, path->m_name, vol_noadouble(vol), addp); + renamefile(vol, p, upath, path->m_name, addp); of_rename(vol, d_of, sdir, spath, curdir, path->m_name); err_src_to_tmp: /* rename temp back to source */ - renamefile(temp, p, spath, vol_noadouble(vol), adsp); + renamefile(vol, temp, p, spath, adsp); of_rename(vol, s_of, curdir, temp, sdir, spath); err_exchangefile: diff --git a/etc/afpd/file.h b/etc/afpd/file.h index 6d6e62d8..1e66e70b 100644 --- a/etc/afpd/file.h +++ b/etc/afpd/file.h @@ -1,5 +1,5 @@ /* - * $Id: file.h,v 1.16.2.2.2.2 2003-09-28 13:58:57 didg Exp $ + * $Id: file.h,v 1.16.2.2.2.3 2004-03-11 02:02:01 didg Exp $ * * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. @@ -129,9 +129,9 @@ extern int getfilparams __P((struct vol *, u_int16_t, struct path *, struct dir *, char *buf, int *)); extern int setfilparams __P((struct vol *, struct path *, u_int16_t, char *)); -extern int renamefile __P((char *, char *, char *, const int, struct adouble *)); -extern int copyfile __P((char *, char *, char *, const int)); -extern int deletefile __P((struct vol *, char *, int)); +extern int renamefile __P((const struct vol *, char *, char *, char *, struct adouble *)); +extern int copyfile __P((const struct vol *, const struct vol *, char *, char *, char *)); +extern int deletefile __P((const struct vol *, char *, int)); extern void *get_finderinfo __P((const char *, struct adouble *, void *)); extern int copy_path_name __P((char *, char *i)); diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index d2c849b7..fb39c1f1 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -1,5 +1,5 @@ /* - * $Id: filedir.c,v 1.45.2.2.2.8 2004-03-02 13:27:07 didg Exp $ + * $Id: filedir.c,v 1.45.2.2.2.9 2004-03-11 02:02:01 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -73,7 +73,7 @@ more information */ return AFPERR_NOOBJ ; } - adpath = ad_path( upath, ADFLAGS_HF ); + adpath = vol->ad_path( upath, ADFLAGS_HF ); /* FIXME dirsearch doesn't move cwd to did ! */ if (( dir = dirlookup( vol, did )) == NULL ) { LOG(log_error, logtype_afpd, "matchfile2dirperms: Unable to get directory info."); @@ -302,7 +302,7 @@ int ibuflen, *rbuflen; } /* -------------------------------------------- - Factorise some check on a pathname + Factorise some checks on a pathname */ int check_name(const struct vol *vol, char *name) { @@ -313,7 +313,7 @@ int check_name(const struct vol *vol, char *name) if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/')) return AFPERR_PARAM; - if (!validupath(vol, name)) + if (!vol->validupath(vol, name)) return AFPERR_EXIST; /* check for vetoed filenames */ @@ -432,12 +432,12 @@ int isdir; if (of_findname(&path)) { rc = AFPERR_EXIST; /* was AFPERR_BUSY; */ } else { - rc = renamefile( p, upath, newname,vol_noadouble(vol), adp ); + rc = renamefile(vol, p, upath, newname, adp ); if (rc == AFP_OK) of_rename(vol, opened, sdir, oldname, curdir, newname); } } else { - rc = renamedir(p, upath, sdir, curdir, newname, vol_noadouble(vol)); + rc = renamedir(vol, p, upath, sdir, curdir, newname); } if ( rc == AFP_OK && id ) { /* renaming may have moved the file/dir across a filesystem */ @@ -764,7 +764,7 @@ int ibuflen, *rbuflen; int admode = ad_mode("", 0777); setfilmode(upath, admode, NULL); - setfilmode(ad_path( upath, ADFLAGS_HF ), ad_hf_mode(admode), NULL); + setfilmode(vol->ad_path( upath, ADFLAGS_HF ), ad_hf_mode(admode), NULL); } setvoltime(obj, vol ); } diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index d569d66e..c066e67f 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.51.2.2.2.6 2004-02-20 21:23:13 didg Exp $ + * $Id: fork.c,v 1.51.2.2.2.7 2004-03-11 02:02:01 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -459,10 +459,12 @@ int ibuflen, *rbuflen; } if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) { - ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path )); - memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path, + if (ad_getentryoff(ofork->of_ad, ADEID_NAME)) { + ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path )); + memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path, ad_getentrylen( ofork->of_ad, ADEID_NAME )); - ad_flush( ofork->of_ad, adflags ); + ad_flush( ofork->of_ad, adflags ); + } } if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ), diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c index 50bccc0a..e07b305b 100644 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@ -1,5 +1,5 @@ /* - * $Id: unix.c,v 1.43.2.1.2.3 2004-02-20 21:23:13 didg Exp $ + * $Id: unix.c,v 1.43.2.1.2.4 2004-03-11 02:02:03 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -364,7 +364,8 @@ const mode_t mode; } /* --------------------- */ -int setfilemode (path, mode) +int setfilunixmode (vol, path, mode) +const struct vol *vol; struct path* path; mode_t mode; { @@ -379,7 +380,7 @@ mode_t mode; if (setfilmode( path->u_name, mode, &path->st) < 0) return -1; /* we need to set write perm if read set for resource fork */ - return setfilmode(ad_path( path->u_name, ADFLAGS_HF ), ad_hf_mode(mode), &path->st); + return setfilmode(vol->ad_path( path->u_name, ADFLAGS_HF ), ad_hf_mode(mode), &path->st); } /* --------------------- */ @@ -405,13 +406,16 @@ mode_t mask = S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH; } /* --------------------- */ -int setdirunixmode( mode, noadouble, dropbox ) -const mode_t mode; -const int noadouble; -const int dropbox; +int setdirunixmode( vol, mode ) +const struct vol *vol; +const mode_t mode; { - if ( stickydirmode(".AppleDouble", DIRBITS | mode, dropbox) < 0 && !noadouble) - return -1 ; + int dropbox = (vol->v_flags & AFPVOL_DROPBOX); + + if (vol->v_adouble != AD_VERSION2_OSX) { + if (stickydirmode(".AppleDouble", DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) + return -1 ; + } if ( stickydirmode(".", DIRBITS | mode, dropbox) < 0 ) return -1; @@ -419,16 +423,18 @@ const int dropbox; } /* --------------------- */ -int setdirmode( mode, noadouble, dropbox ) +int setdirmode( vol, mode ) +const struct vol *vol; const mode_t mode; -const int noadouble; -const int dropbox; { char buf[ MAXPATHLEN + 1]; struct stat st; char *m; struct dirent *dirp; DIR *dir; + int osx = vol->v_adouble == AD_VERSION2_OSX; + int hf_mode = ad_hf_mode(mode); + int dropbox = (vol->v_flags & AFPVOL_DROPBOX); if (( dir = opendir( "." )) == NULL ) { LOG(log_error, logtype_afpd, "setdirmode: opendir .: %s", strerror(errno) ); @@ -436,7 +442,8 @@ const int dropbox; } for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) { - if ( *dirp->d_name == '.' ) { + /* FIXME */ + if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) { continue; } if ( stat( dirp->d_name, &st ) < 0 ) { @@ -446,7 +453,9 @@ const int dropbox; } if (!S_ISDIR(st.st_mode)) { - if (setfilmode(dirp->d_name, mode, &st) < 0) { + int setmode = (osx && *dirp->d_name == '.')?hf_mode:mode; + + if (setfilmode(dirp->d_name, setmode, &st) < 0) { LOG(log_error, logtype_afpd, "setdirmode: chmod %s: %s", dirp->d_name, strerror(errno) ); return -1; @@ -463,11 +472,15 @@ const int dropbox; #endif } closedir( dir ); - + + if (osx) { + goto setdirmode_noadouble; + } + /* change perm of .AppleDouble's files */ if (( dir = opendir( ".AppleDouble" )) == NULL ) { - if (noadouble) + if (vol_noadouble(vol)) goto setdirmode_noadouble; LOG(log_error, logtype_afpd, "setdirmode: opendir .AppleDouble: %s", strerror(errno) ); return( -1 ); @@ -488,7 +501,7 @@ const int dropbox; continue; } if (!S_ISDIR(st.st_mode)) { - if (setfilmode(buf, ad_hf_mode(mode), &st) < 0) { + if (setfilmode(buf, hf_mode , &st) < 0) { /* FIXME what do we do then? */ } } @@ -574,28 +587,31 @@ const gid_t gid; } -/* uid/gid == 0 need to be handled as special cases. they really mean +/* --------------------------------- + * uid/gid == 0 need to be handled as special cases. they really mean * that user/group should inherit from other, but that doesn't fit * into the unix permission scheme. we can get around this by * co-opting some bits. */ -int setdirowner( uid, gid, noadouble ) +int setdirowner(vol, uid, gid ) +const struct vol *vol; const uid_t uid; const gid_t gid; -const int noadouble; { char buf[ MAXPATHLEN + 1]; struct stat st; char *m; struct dirent *dirp; DIR *dir; + int osx = vol->v_adouble == AD_VERSION2_OSX; + int noadouble = vol_noadouble(vol); if (( dir = opendir( "." )) == NULL ) { return( -1 ); } for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) { - if ( *dirp->d_name == '.' ) { + if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) { continue; - }; + } if ( stat( dirp->d_name, &st ) < 0 ) { LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", dirp->d_name, strerror(errno) ); @@ -610,6 +626,11 @@ const int noadouble; } } closedir( dir ); + + if (osx) { + goto setdirowner_noadouble; + } + if (( dir = opendir( ".AppleDouble" )) == NULL ) { if (noadouble) goto setdirowner_noadouble; diff --git a/etc/afpd/unix.h b/etc/afpd/unix.h index 70d82cd4..25ed2da2 100644 --- a/etc/afpd/unix.h +++ b/etc/afpd/unix.h @@ -1,5 +1,5 @@ /* - * $Id: unix.h,v 1.12.2.1.2.2 2004-01-07 13:33:03 lenneis Exp $ + * $Id: unix.h,v 1.12.2.1.2.3 2004-03-11 02:02:03 didg Exp $ */ #ifndef AFPD_UNIX_H @@ -217,12 +217,12 @@ extern struct afp_options default_options; extern int gmem __P((const gid_t)); extern int setdeskmode __P((const mode_t)); -extern int setdirunixmode __P((const mode_t, const int, const int)); -extern int setdirmode __P((const mode_t, const int, const int)); +extern int setdirunixmode __P((const struct vol *, const mode_t)); +extern int setdirmode __P((const struct vol *, const mode_t)); extern int setdeskowner __P((const uid_t, const gid_t)); -extern int setdirowner __P((const uid_t, const gid_t, const int)); +extern int setdirowner __P((const struct vol *, const uid_t, const gid_t)); extern int setfilmode __P((char *, mode_t , struct stat *)); -extern int setfilemode __P((struct path*, const mode_t)); +extern int setfilunixmode __P((const struct vol *, struct path*, const mode_t)); extern int unix_rename __P((const char *oldpath, const char *newpath)); extern void accessmode __P((char *, struct maccess *, struct dir *, struct stat *)); diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 4b03f06b..f42076aa 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -1,5 +1,5 @@ /* - * $Id: volume.c,v 1.51.2.7.2.24 2004-03-02 13:27:08 didg Exp $ + * $Id: volume.c,v 1.51.2.7.2.25 2004-03-11 02:02:03 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -391,6 +391,8 @@ static void volset(struct vol_option *options, struct vol_option *save, #if AD_VERSION == AD_VERSION2 else if (strcasecmp(val + 1, "v2") == 0) options[VOLOPT_ADOUBLE].i_value = AD_VERSION2; + else if (strcasecmp(val + 1, "osx") == 0) + options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX; #endif } else if (optionok(tmp, "options:", val)) { char *p; @@ -487,6 +489,34 @@ static void showvol(const ucs2_t *name) } } +/* ----------------- + * FIXME should be define elsewhere +*/ +static int validupath_adouble(const struct vol *vol, const char *name) +{ + return (vol->v_flags & AFPVOL_USEDOTS) ? strncasecmp(name,".Apple", 6) && strcasecmp(name, ".Parent") + : name[0] != '.'; +} + +/* ----------------- */ +static int validupath_osx(const struct vol *vol, const char *name) +{ + return strncasecmp(name,".Apple", 6) && strncasecmp(name,"._", 2); +} + +/* ---------------- */ +static void initvoladouble(struct vol *vol) +{ + if (vol->v_adouble == AD_VERSION2_OSX) { + vol->validupath = validupath_osx; + vol->ad_path = ad_path_osx; + } + else { + vol->validupath = validupath_adouble; + vol->ad_path = ad_path; + } +} + /* ------------------------------- */ static int creatvol(AFPObj *obj, struct passwd *pwd, char *path, char *name, @@ -589,6 +619,7 @@ static int creatvol(AFPObj *obj, struct passwd *pwd, volume->v_adouble = options[VOLOPT_ADOUBLE].i_value; else volume->v_adouble = AD_VERSION; + initvoladouble(volume); #ifdef FORCE_UIDGID if (options[VOLOPT_FORCEUID].c_value) { volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value); @@ -1170,10 +1201,11 @@ int *buflen; slash++; else slash = vol->v_path; - - ad_setentrylen( &ad, ADEID_NAME, strlen( slash )); - memcpy(ad_entry( &ad, ADEID_NAME ), slash, + if (ad_getentryoff(&ad, ADEID_NAME)) { + ad_setentrylen( &ad, ADEID_NAME, strlen( slash )); + memcpy(ad_entry( &ad, ADEID_NAME ), slash, ad_getentrylen( &ad, ADEID_NAME )); + } vol_setdate(vol->v_vid, &ad, st->st_mtime); ad_flush(&ad, ADFLAGS_HF); } @@ -2066,9 +2098,11 @@ static int create_special_folder (const struct vol *vol, const struct _special_f return (-1); } if ((ad_get_HF_flags( &ad ) & O_CREAT) ) { - ad_setentrylen( &ad, ADEID_NAME, strlen(folder->name)); - memcpy(ad_entry( &ad, ADEID_NAME ), folder->name, - ad_getentrylen( &ad, ADEID_NAME )); + if (ad_getentryoff(&ad, ADEID_NAME)) { + ad_setentrylen( &ad, ADEID_NAME, strlen(folder->name)); + memcpy(ad_entry( &ad, ADEID_NAME ), folder->name, + ad_getentrylen( &ad, ADEID_NAME )); + } } ad_getattr(&ad, &attr); diff --git a/etc/afpd/volume.h b/etc/afpd/volume.h index e82d5352..46fb94e0 100644 --- a/etc/afpd/volume.h +++ b/etc/afpd/volume.h @@ -1,5 +1,5 @@ /* - * $Id: volume.h,v 1.19.2.5.2.5 2004-01-03 22:21:09 didg Exp $ + * $Id: volume.h,v 1.19.2.5.2.6 2004-03-11 02:02:04 didg Exp $ * * Copyright (c) 1990,1994 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -77,6 +77,10 @@ struct vol { int v_root_preexec_close; int v_preexec_close; + + /* adouble indirection */ + int (*validupath)(const struct vol *, const char *); + char *(*ad_path)(const char *, int); }; #ifdef NO_LARGE_VOL_SUPPORT diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index 8f137032..bace1fdd 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -1,5 +1,5 @@ /* - * $Id: adouble.h,v 1.21.6.12 2004-02-20 20:53:14 bfernhomberg Exp $ + * $Id: adouble.h,v 1.21.6.13 2004-03-11 02:02:04 didg Exp $ * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. * @@ -77,6 +77,7 @@ /* version info */ #define AD_VERSION1 0x00010000 #define AD_VERSION2 0x00020000 +#define AD_VERSION2_OSX 0x00020001 #define AD_VERSION AD_VERSION2 /* @@ -246,6 +247,8 @@ struct adouble { off_t ad_rlen; /* ressource fork len with AFP 3.0 the header parameter size is too small. */ + char *(*ad_path)(const char *, int); + #ifdef USE_MMAPPED_HEADERS char *ad_data; #else @@ -350,18 +353,20 @@ extern int ad_excl_lock __P((struct adouble * /*adp*/, const u_int32_t /*eid #define ad_unlock ad_fcntl_unlock /* ad_open.c */ -extern int ad_setfuid __P((const uid_t )); -extern uid_t ad_getfuid __P((void )); - -extern char *ad_dir __P((const char *)); -extern char *ad_path __P((const char *, int)); -extern int ad_mode __P((const char *, int)); -extern int ad_mkdir __P((const char *, int)); -extern void ad_init __P((struct adouble *, int )); - -extern int ad_open __P((const char *, int, int, int, struct adouble *)); -extern int ad_refresh __P((struct adouble *)); -extern int ad_stat __P((const char *, struct stat *)); +extern int ad_setfuid __P((const uid_t )); +extern uid_t ad_getfuid __P((void )); + +extern char *ad_dir __P((const char *)); +extern char *ad_path __P((const char *, int)); +extern char *ad_path_osx __P((const char *, int)); + +extern int ad_mode __P((const char *, int)); +extern int ad_mkdir __P((const char *, int)); +extern void ad_init __P((struct adouble *, int )); + +extern int ad_open __P((const char *, int, int, int, struct adouble *)); +extern int ad_refresh __P((struct adouble *)); +extern int ad_stat __P((const char *, struct stat *)); /* extend header to RW if R or W (W if R for locking), */ diff --git a/libatalk/adouble/ad_attr.c b/libatalk/adouble/ad_attr.c index 49c8ff8e..5282485b 100644 --- a/libatalk/adouble/ad_attr.c +++ b/libatalk/adouble/ad_attr.c @@ -1,5 +1,5 @@ /* - * $Id: ad_attr.c,v 1.4.8.3 2004-02-06 13:39:52 bfernhomberg Exp $ + * $Id: ad_attr.c,v 1.4.8.4 2004-03-11 02:02:05 didg Exp $ */ #ifdef HAVE_CONFIG_H @@ -14,34 +14,49 @@ int ad_getattr(const struct adouble *ad, u_int16_t *attr) { - if (ad->ad_version == AD_VERSION1) - memcpy(attr, ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, - sizeof(u_int16_t)); + *attr = 0; + + if (ad->ad_version == AD_VERSION1) { + if (ad_getentryoff(ad, ADEID_FILEI)) { + memcpy(attr, ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, + sizeof(u_int16_t)); + } + } #if AD_VERSION == AD_VERSION2 - else if (ad->ad_version == AD_VERSION2) - memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, - sizeof(u_int16_t)); + else if (ad->ad_version == AD_VERSION2) { + if (ad_getentryoff(ad, ADEID_AFPFILEI)) { + memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, + sizeof(u_int16_t)); + } + } #endif - else - return -1; + else + return -1; - return 0; + return 0; } +/* ----------------- */ int ad_setattr(const struct adouble *ad, const u_int16_t attr) { - if (ad->ad_version == AD_VERSION1) - memcpy(ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, &attr, - sizeof(attr)); + if (ad->ad_version == AD_VERSION1) { + if (ad_getentryoff(ad, ADEID_FILEI)) { + memcpy(ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, &attr, + sizeof(attr)); + } + } #if AD_VERSION == AD_VERSION2 - else if (ad->ad_version == AD_VERSION2) - memcpy(ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, &attr, - sizeof(attr)); + else if (ad->ad_version == AD_VERSION2) { + if (ad_getentryoff(ad, ADEID_AFPFILEI)) { + memcpy(ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, &attr, + sizeof(attr)); + } + } #endif - else - return -1; + else + return -1; - return 0; + return 0; } /* -------------- @@ -50,7 +65,8 @@ int ad_setattr(const struct adouble *ad, const u_int16_t attr) #if AD_VERSION == AD_VERSION2 int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const u_int32_t id, const cnid_t did, const void *stamp) { - if (adp->ad_flags == AD_VERSION2 && sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO) + if (adp->ad_flags == AD_VERSION2 && ad_getentryoff(adp, ADEID_PRIVDEV) && + sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO) { ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t)); memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t)); diff --git a/libatalk/adouble/ad_date.c b/libatalk/adouble/ad_date.c index 5ec1beba..1742af84 100644 --- a/libatalk/adouble/ad_date.c +++ b/libatalk/adouble/ad_date.c @@ -1,5 +1,5 @@ /* - * $Id: ad_date.c,v 1.3.14.2 2004-02-20 20:18:33 didg Exp $ + * $Id: ad_date.c,v 1.3.14.3 2004-03-11 02:02:05 didg Exp $ */ #ifdef HAVE_CONFIG_H @@ -24,8 +24,11 @@ int ad_setdate(const struct adouble *ad, memcpy(ad_entry(ad, ADEID_FILEI) + dateoff, &date, sizeof(date)); } else if (ad->ad_version == AD_VERSION2) { + if (!ad_getentryoff(ad, ADEID_FILEDATESI)) + return -1; + if (dateoff > AD_DATE_ACCESS) - return -1; + return -1; memcpy(ad_entry(ad, ADEID_FILEDATESI) + dateoff, &date, sizeof(date)); } else @@ -46,6 +49,9 @@ int ad_getdate(const struct adouble *ad, memcpy(date, ad_entry(ad, ADEID_FILEI) + dateoff, sizeof(u_int32_t)); } else if (ad->ad_version == AD_VERSION2) { + if (!ad_getentryoff(ad, ADEID_FILEDATESI)) + return -1; + if (dateoff > AD_DATE_ACCESS) return -1; memcpy(date, ad_entry(ad, ADEID_FILEDATESI) + dateoff, sizeof(u_int32_t)); diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 09741757..6e14a715 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -1,5 +1,5 @@ /* - * $Id: ad_open.c,v 1.30.6.8 2004-02-20 19:57:14 didg Exp $ + * $Id: ad_open.c,v 1.30.6.9 2004-03-11 02:02:05 didg Exp $ * * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) * Copyright (c) 1990,1991 Regents of The University of Michigan. @@ -111,6 +111,10 @@ #define ADEDOFF_RFORK_V2 (ADEDOFF_PRIVID + ADEDLEN_PRIVID) +#define ADEID_NUM_OSX 2 +#define ADEDOFF_FINDERI_OSX (AD_HEADER_LEN + ADEID_NUM_OSX*AD_ENTRY_LEN) +#define ADEDOFF_RFORK_OSX (ADEDOFF_FINDERI_OSX + ADEDLEN_FINDERI) + /* we keep local copies of a bunch of stuff so that we can initialize things * correctly. */ @@ -191,6 +195,16 @@ static const struct entry entry_order2[ADEID_NUM_V2 +1] = { {0, 0, 0} }; + +/* OS X adouble finder info and resource fork only +*/ +static const struct entry entry_order_osx[ADEID_NUM_OSX +1] = { + {ADEID_FINDERI, ADEDOFF_FINDERI_OSX, ADEDLEN_FINDERI}, + {ADEID_RFORK, ADEDOFF_RFORK_OSX, ADEDLEN_INIT}, + + {0, 0, 0} +}; + #endif /* AD_VERSION == AD_VERSION2 */ #if AD_VERSION == AD_VERSION2 @@ -206,7 +220,7 @@ static int ad_update(struct adouble *ad, const char *path) int fd; /* check to see if we should convert this header. */ - if (!path || (ad->ad_version != AD_VERSION2)) + if (!path || (ad->ad_flags != AD_VERSION2)) return 0; if (ad->ad_eid[ADEID_RFORK].ade_off) @@ -315,7 +329,7 @@ static int ad_v1tov2(struct adouble *ad, const char *path) return 0; /* we want version1 anyway */ - if (ad->ad_flags == AD_VERSION1) + if (ad->ad_flags != AD_VERSION2) return 0; @@ -622,8 +636,7 @@ static int ad_header_read(struct adouble *ad, struct stat *hst) return 0; } - -/* +/* --------------------------------------- * Put the .AppleDouble where it needs to be: * * / a/.AppleDouble/b @@ -666,6 +679,39 @@ ad_path( path, adflags ) return( pathbuf ); } +/* --------------------------------------- + * Put the resource fork where it needs to be: + * ._name + */ +char * +ad_path_osx( path, adflags ) + const char *path; + int adflags; +{ + static char pathbuf[ MAXPATHLEN + 1]; + char c, *slash, buf[MAXPATHLEN + 1]; + + if (!strcmp(path,".")) { + /* fixme */ + getcwd(buf, MAXPATHLEN); + } + else { + strncpy(buf, path, MAXPATHLEN); + } + if (NULL != ( slash = strrchr( buf, '/' )) ) { + c = *++slash; + *slash = '\0'; + strncpy( pathbuf, buf, MAXPATHLEN); + *slash = c; + } else { + pathbuf[ 0 ] = '\0'; + slash = buf; + } + strncat( pathbuf, "._", MAXPATHLEN - strlen(pathbuf)); + strncat( pathbuf, slash, MAXPATHLEN - strlen(pathbuf)); + return pathbuf; +} + /* * Support inherited protection modes for AppleDouble files. The supplied * mode is ANDed with the parent directory's mask value in lieu of "umask", @@ -847,6 +893,12 @@ void ad_init(struct adouble *ad, int flags) { memset( ad, 0, sizeof( struct adouble ) ); ad->ad_flags = flags; + if (flags == AD_VERSION2_OSX) { + ad->ad_path = ad_path_osx; + } + else { + ad->ad_path = ad_path; + } } /* ------------------- @@ -933,7 +985,7 @@ int ad_open( path, adflags, oflags, mode, ad ) return 0; } - ad_p = ad_path( path, adflags ); + ad_p = ad->ad_path( path, adflags ); hoflags = oflags & ~O_CREAT; hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; @@ -957,7 +1009,7 @@ int ad_open( path, adflags, oflags, mode, ad ) admode = ad_hf_mode(admode); errno = 0; ad->ad_hf.adf_fd = open( ad_p, oflags,admode ); - if ( ad->ad_hf.adf_fd < 0 ) { + if ( ad->ad_hf.adf_fd < 0 && ad->ad_flags != AD_VERSION2_OSX) { /* * Probably .AppleDouble doesn't exist, try to * mkdir it. @@ -976,13 +1028,11 @@ int ad_open( path, adflags, oflags, mode, ad ) st_invalid = ad_mode_st(ad_p, &admode, &st); admode = ad_hf_mode(admode); ad->ad_hf.adf_fd = open( ad_p, oflags, admode); - if ( ad->ad_hf.adf_fd < 0 ) { - return ad_error(ad, adflags); - } - } else { - return ad_error(ad, adflags); } } + if ( ad->ad_hf.adf_fd < 0 ) { + return ad_error(ad, adflags); + } ad->ad_hf.adf_flags = oflags; /* just created, set owner if admin owner (root) */ if (!st_invalid) { @@ -1029,24 +1079,24 @@ int ad_open( path, adflags, oflags, mode, ad ) /* ----------------------------------- */ static int new_rfork(const char *path, struct adouble *ad, int adflags) { -#if 0 - struct timeval tv; -#endif const struct entry *eid; u_int16_t ashort; struct stat st; ad->ad_magic = AD_MAGIC; - ad->ad_version = ad->ad_flags; - if (!ad->ad_version) - ad->ad_version = AD_VERSION; + ad->ad_version = ad->ad_flags & 0x0f0000; + if (!ad->ad_version) { + ad->ad_version = AD_VERSION; + } memset(ad->ad_filler, 0, sizeof( ad->ad_filler )); memset(ad->ad_data, 0, sizeof(ad->ad_data)); #if AD_VERSION == AD_VERSION2 - if (ad->ad_version == AD_VERSION2) + if (ad->ad_flags == AD_VERSION2) eid = entry_order2; + else if (ad->ad_flags == AD_VERSION2_OSX) + eid = entry_order_osx; else #endif eid = entry_order1; @@ -1078,12 +1128,6 @@ static int new_rfork(const char *path, struct adouble *ad, int adflags) &ashort, sizeof(ashort)); } -#if 0 - if (gettimeofday(&tv, NULL) < 0) { - return -1; - } -#endif - if (stat(path, &st) < 0) { return -1; } -- 2.39.2