From: Frank Lahm Date: Thu, 26 Jan 2012 11:05:38 +0000 (+0100) Subject: Change setdirparams logic and order of changing perms X-Git-Url: https://arthur.barton.de/gitweb/?p=netatalk.git;a=commitdiff_plain;h=6aa3f324ef50bd6a6241739da872541bdb2c5705 Change setdirparams logic and order of changing perms --- diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 53bfb201..4b301649 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1796,8 +1797,6 @@ int afp_setdirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ } /* - * cf AFP3.0.pdf page 244 for change_mdate and change_parent_mdate logic - * * assume path == '\0' eg. it's a directory in canonical form */ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *buf ) @@ -1821,7 +1820,9 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu u_char finder_buf[32]; uint32_t upriv; mode_t mpriv = 0; - uint16_t upriv_bit = 0; + bool set_upriv = false, set_maccess = false; + + LOG(log_debug, logtype_afpd, "setdirparams(%s)", path->u_name); bit = 0; upath = path->u_name; @@ -1858,27 +1859,21 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu buf += 32; break; case DIRPBIT_UID : /* What kind of loser mounts as root? */ - change_parent_mdate = 1; memcpy( &owner, buf, sizeof(owner)); buf += sizeof( owner ); break; case DIRPBIT_GID : - change_parent_mdate = 1; memcpy( &group, buf, sizeof( group )); buf += sizeof( group ); break; case DIRPBIT_ACCESS : + set_maccess = true; change_mdate = 1; - change_parent_mdate = 1; ma.ma_user = *buf++; ma.ma_world = *buf++; ma.ma_group = *buf++; ma.ma_owner = *buf++; mpriv = mtoumode( &ma ) | vol->v_dperm; - if (dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) { - err = set_dir_errors(path, "setdirmode", errno); - bitmap = 0; - } break; /* Ignore what the client thinks we should do to the ProDOS information block. Skip over the data and @@ -1894,27 +1889,16 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu break; case DIRPBIT_UNIXPR : if (vol_unix_priv(vol)) { + set_upriv = true; memcpy( &owner, buf, sizeof(owner)); /* FIXME need to change owner too? */ buf += sizeof( owner ); memcpy( &group, buf, sizeof( group )); buf += sizeof( group ); change_mdate = 1; - change_parent_mdate = 1; memcpy( &upriv, buf, sizeof( upriv )); buf += sizeof( upriv ); upriv = ntohl (upriv) | vol->v_dperm; - if (dir_rx_set(upriv)) { - /* maybe we are trying to set perms back */ - if ( setdirunixmode(vol, upath, upriv) < 0 ) { - bitmap = 0; - err = set_dir_errors(path, "setdirunixmode", errno); - } - } - else { - /* do it later */ - upriv_bit = 1; - } break; } /* fall through */ @@ -1938,6 +1922,7 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu * note: we also don't need to worry about mdate. also, be quiet * if we're using the noadouble option. */ + if (!vol_noadouble(vol) && (d_bitmap & ~((1<d_did == DIRDID_ROOT) { - setdeskmode(mpriv); - if (!dir_rx_set(mpriv)) { - /* we can't remove read and search for owner on volume root */ - err = AFPERR_ACCESS; - goto setdirparam_done; - } - } - - if (!dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) { - err = set_dir_errors(path, "setdirmode", errno); - goto setdirparam_done; - } break; case DIRPBIT_PDINFO : if (afp_version >= 30) { @@ -2059,27 +2031,7 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu } break; case DIRPBIT_UNIXPR : - if (vol_unix_priv(vol)) { - if (dir->d_did == DIRDID_ROOT) { - if (!dir_rx_set(upriv)) { - /* we can't remove read and search for owner on volume root */ - err = AFPERR_ACCESS; - goto setdirparam_done; - } - setdeskowner( -1, ntohl(group) ); - setdeskmode( upriv ); - } - if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) { - err = set_dir_errors(path, "setdirowner", errno); - goto setdirparam_done; - } - - if ( upriv_bit && setdirunixmode(vol, upath, upriv) < 0 ) { - err = set_dir_errors(path, "setdirunixmode", errno); - goto setdirparam_done; - } - } - else { + if (!vol_unix_priv(vol)) { err = AFPERR_BITMAP; goto setdirparam_done; } @@ -2113,10 +2065,55 @@ setdirparam_done: ad_setid(&ad, st->st_dev, st->st_ino, dir->d_did, dir->d_pdid, vol->v_stamp); } } - ad_flush(&ad); + if (ad_flush(&ad) != 0) { + switch (errno) { + case EACCES: + err = AFPERR_ACCESS; + break; + default: + err = AFPERR_MISC; + break; + } + } ad_close(&ad, ADFLAGS_HF); } + if (err == AFP_OK) { + if (set_maccess == true) { + if (dir->d_did == DIRDID_ROOT) { + setdeskmode(mpriv); + if (!dir_rx_set(mpriv)) { + /* we can't remove read and search for owner on volume root */ + err = AFPERR_ACCESS; + goto setprivdone; + } + } + if (setdirmode(vol, upath, mpriv) < 0) + err = set_dir_errors(path, "setdirmode", errno); + } + if ((set_upriv == true) && vol_unix_priv(vol)) { + if (dir->d_did == DIRDID_ROOT) { + if (!dir_rx_set(upriv)) { + /* we can't remove read and search for owner on volume root */ + err = AFPERR_ACCESS; + goto setprivdone; + } + setdeskowner(-1, ntohl(group)); + setdeskmode(upriv); + } + + if (setdirowner(vol, upath, -1, ntohl(group)) < 0) { + err = set_dir_errors(path, "setdirowner", errno); + goto setprivdone; + } + + + if (setdirunixmode(vol, upath, upriv) < 0) + err = set_dir_errors(path, "setdirunixmode", errno); + } + } + +setprivdone: if (change_parent_mdate && dir->d_did != DIRDID_ROOT && gettimeofday(&tv, NULL) == 0) { if (movecwd(vol, dirlookup(vol, dir->d_pdid)) == 0) { @@ -2127,7 +2124,6 @@ setdirparam_done: /* should we reset curdir ?*/ } } - return err; } diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index 67eb3201..de2bd07b 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -506,7 +506,35 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size upath = s_path->u_name; if ( path_isadir( s_path) ) { if (*s_path->m_name != '\0' || curdir->d_did == DIRDID_ROOT) { - rc = AFPERR_ACCESS; + if (vol->v_adouble == AD_VERSION2) { + rc = AFPERR_ACCESS; + } else { + if (rmdir(upath) != 0) { + switch (errno) { + case ENOTEMPTY: + rc = AFPERR_DIRNEMPT; + break; + case EACCES: + rc = AFPERR_ACCESS; + break; + default: + rc = AFPERR_MISC; + break; + } + } else { + struct dir *deldir; + cnid_t delcnid = CNID_INVALID; + if ((deldir = dircache_search_by_name(vol, curdir, upath, strlen(upath)))) { + delcnid = deldir->d_did; + dir_remove(vol, deldir); + } + if (delcnid == CNID_INVALID) + delcnid = cnid_get(vol->v_cdb, curdir->d_did, upath, strlen(upath)); + if (delcnid != CNID_INVALID) + cnid_delete(vol->v_cdb, delcnid); + fce_register_delete_dir(upath); + } + } } else { /* we have to cache this, the structs are lost in deletcurdir*/ /* but we need the positive returncode to send our event */ diff --git a/include/atalk/volume.h b/include/atalk/volume.h index 6d651128..ca2aa87c 100644 --- a/include/atalk/volume.h +++ b/include/atalk/volume.h @@ -191,8 +191,8 @@ int wincheck(const struct vol *vol, const char *path); #define utf8_encoding() (afp_version >= 30) -#define vol_noadouble(vol) ((((vol)->v_flags & AFPVOL_NOADOUBLE) \ - || ((vol)->v_adouble & AD_VERSION_EA)) ? 1 : 0) +// TODO: remove AFPVOL_NOADOUBLE +#define vol_noadouble(vol) (((vol)->v_flags & AFPVOL_NOADOUBLE) ? 1 : 0) #define vol_nodev(vol) (((vol)->v_flags & AFPVOL_NODEV) ? 1 : 0) #define vol_unix_priv(vol) (afp_version >= 30 && ((vol)->v_flags & AFPVOL_UNIX_PRIV)) #define vol_inv_dots(vol) (((vol)->v_flags & AFPVOL_INV_DOTS) ? 1 : 0)