/*
- * $Id: directory.c,v 1.33 2002-05-27 04:47:00 didg Exp $
+ * $Id: directory.c,v 1.41.2.2 2002-11-07 17:10:02 srittau Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "globals.h"
#include "unix.h"
-#ifdef FORCE_UIDGID
-#include "uid.h"
-#endif /* FORCE_UIDGID */
-
struct dir *curdir;
#define SENTINEL (&sentinel)
char *ptr;
static char buffer[12 + MAXPATHLEN + 1];
int buflen = 12 + MAXPATHLEN + 1;
-
+ char *mpath;
+
ret = dirsearch(vol, did);
if (ret != NULL)
return ret;
return NULL;
}
ptr = path + MAXPATHLEN;
- len = strlen(upath);
+ mpath = utompath(vol, upath);
+ len = strlen(mpath);
pathlen = len; /* no 0 in the last part */
len++;
- strcpy(ptr - len, upath);
+ strcpy(ptr - len, mpath);
ptr -= len;
while (1) {
ret = dirsearch(vol,id);
}
if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL)
return NULL;
- len = strlen(upath) + 1;
+ mpath = utompath(vol, upath);
+ len = strlen(mpath) + 1;
pathlen += len;
if (pathlen > 255)
return NULL;
- strcpy(ptr - len, upath);
+ strcpy(ptr - len, mpath);
ptr -= len;
}
/* fill the cache */
if ( !extend ) {
cdir = dir->d_child;
while (cdir) {
- if ( strcasecmp( cdir->d_name, path ) == 0 ) {
+ if ( strcmp( cdir->d_name, path ) == 0 ) {
break;
}
cdir = (cdir == dir->d_child->d_prev) ? NULL :
/* dir is not valid anymore
we delete dir from the cache and abort.
*/
- dir_invalidate(vol, dir);
+ if ( dir->d_did != DIRDID_ROOT_PARENT)
+ dir_invalidate(vol, dir);
return( NULL );
}
cdir = extenddir( vol, dir, path );
int bit = 0, isad = 1;
u_int32_t aint;
u_int16_t ashort;
-#ifdef FORCE_UIDGID
- uidgidset *uidgid;
- memset(&uidgid, 0, sizeof(uidgid));
-#endif /* FORCE_UIDGID */
memset(&ad, 0, sizeof(ad));
-#ifdef FORCE_UIDGID
- save_uidgid ( &uidgid );
- set_uidgid ( vol );
-#endif /* FORCE_UIDGID */
-
if ( ad_open( upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
DIRBITS | 0777, &ad) < 0 ) {
isad = 0;
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
+ ashort |= htons(ATTRBIT_SHARED);
memcpy( data, &ashort, sizeof( ashort ));
data += sizeof( ashort );
break;
break;
case DIRPBIT_ACCESS :
- utommode( st, &ma );
-#ifndef SENDFILE_FLAVOR_LINUX /* ignore this section if it's linux */
-#ifdef HAVE_ACCESS
- accessmode( upath, &ma, dir );
-#endif /* HAVE_ACCESS */
-#endif /* SENDFILE_FLAVOR_LINUX */
-#ifdef AFS /* If only AFS defined, access() works only for AFS filesystems */
- afsmode( upath, &ma, dir );
-#endif /* AFS */
+ accessmode( upath, &ma, dir , st);
+
*data++ = ma.ma_user;
*data++ = ma.ma_world;
*data++ = ma.ma_group;
if ( isad ) {
ad_close( &ad, ADFLAGS_HF );
}
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_BITMAP );
}
bitmap = bitmap>>1;
memcpy( &did, ibuf, sizeof( did ));
ibuf += sizeof( int );
- if (( dir = dirsearch( vol, did )) == NULL ) {
+ if (( dir = dirlookup( vol, did )) == NULL ) {
return( AFPERR_NOOBJ );
}
return( AFPERR_NOOBJ );
}
+ if ( *path != '\0' ) {
+ return( AFPERR_BADTYPE ); /* not a directory */
+ }
+
/*
* If ibuf is odd, make it even.
*/
return( rc );
}
-int setdirparams(const struct vol *vol,
+/*
+ * 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(const struct vol *vol,
char *path, u_int16_t bitmap, char *buf )
{
struct maccess ma;
struct adouble ad;
struct utimbuf ut;
+ struct timeval tv;
+
char *upath;
int bit = 0, aint, isad = 1;
u_int16_t ashort, bshort;
int err = AFP_OK;
-#ifdef FORCE_UIDGID
- uidgidset *uidgid;
-
- memset(&uidgid, 0, sizeof(uidgid));
-#endif /* FORCE_UIDGID */
+ int change_mdate = 0;
+ int change_parent_mdate = 0;
+ int newdate = 0;
upath = mtoupath(vol, path);
memset(&ad, 0, sizeof(ad));
-#ifdef FORCE_UIDGID
- save_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
+
if (ad_open( upath, vol_noadouble(vol)|ADFLAGS_HF|ADFLAGS_DIR,
O_RDWR|O_CREAT, 0666, &ad) < 0) {
/*
if (!vol_noadouble(vol) && (bitmap &
~((1<<DIRPBIT_ACCESS)|(1<<DIRPBIT_UID)|(1<<DIRPBIT_GID)|
(1<<DIRPBIT_MDATE)|(1<<DIRPBIT_PDINFO)))) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_ACCESS;
}
switch( bit ) {
case DIRPBIT_ATTR :
+ change_mdate = 1;
if (isad) {
memcpy( &ashort, buf, sizeof( ashort ));
ad_getattr(&ad, &bshort);
bshort &= ~ashort;
}
ad_setattr(&ad, bshort);
+ if ((ashort & htons(ATTRBIT_INVISIBLE)))
+ change_parent_mdate = 1;
}
buf += sizeof( ashort );
break;
case DIRPBIT_CDATE :
+ change_mdate = 1;
if (isad) {
memcpy(&aint, buf, sizeof(aint));
ad_setdate(&ad, AD_DATE_CREATE, aint);
break;
case DIRPBIT_MDATE :
- memcpy(&aint, buf, sizeof(aint));
- if (isad)
- ad_setdate(&ad, AD_DATE_MODIFY, aint);
- ut.actime = ut.modtime = AD_DATE_TO_UNIX(aint);
- utime(upath, &ut);
- buf += sizeof( aint );
+ memcpy(&newdate, buf, sizeof(newdate));
+ buf += sizeof( newdate );
break;
case DIRPBIT_BDATE :
+ change_mdate = 1;
if (isad) {
memcpy(&aint, buf, sizeof(aint));
ad_setdate(&ad, AD_DATE_BACKUP, aint);
break;
case DIRPBIT_FINFO :
+ change_mdate = 1;
/*
* Alright, we admit it, this is *really* sick!
* The 4 bytes that we don't copy, when we're dealing
break;
case DIRPBIT_UID : /* What kind of loser mounts as root? */
+ change_parent_mdate = 1;
memcpy( &aint, buf, sizeof(aint));
buf += sizeof( aint );
if ( (curdir->d_did == DIRDID_ROOT) &&
}
break;
case DIRPBIT_GID :
+ change_parent_mdate = 1;
memcpy( &aint, buf, sizeof( aint ));
buf += sizeof( aint );
if (curdir->d_did == DIRDID_ROOT)
break;
case DIRPBIT_ACCESS :
+ change_mdate = 1;
+ change_parent_mdate = 1;
ma.ma_user = *buf++;
ma.ma_world = *buf++;
ma.ma_group = *buf++;
err = AFPERR_PARAM;
goto setdirparam_done;
}
- }
#endif /* 0 */
- if ( setdirmode( mtoumode( &ma ), vol_noadouble(vol),
+ if ( setdirmode( mtoumode( &ma ), vol_noadouble(vol),
(vol->v_flags & AFPVOL_DROPBOX)) < 0 ) {
- switch ( errno ) {
- case EPERM :
- case EACCES :
- err = AFPERR_ACCESS;
- goto setdirparam_done;
- case EROFS :
- err = AFPERR_VLOCK;
- goto setdirparam_done;
- default :
- LOG(log_error, logtype_afpd, "setdirparam: setdirmode: %s",
- strerror(errno) );
- err = AFPERR_PARAM;
- goto setdirparam_done;
+ switch ( errno ) {
+ case EPERM :
+ case EACCES :
+ err = AFPERR_ACCESS;
+ goto setdirparam_done;
+ case EROFS :
+ err = AFPERR_VLOCK;
+ goto setdirparam_done;
+ default :
+ LOG(log_error, logtype_afpd, "setdirparam: setdirmode: %s",
+ strerror(errno) );
+ err = AFPERR_PARAM;
+ goto setdirparam_done;
+ }
}
- }
- break;
+ break;
/* Ignore what the client thinks we should do to the
ProDOS information block. Skip over the data and
report nothing amiss. <shirsch@ibm.net> */
- case DIRPBIT_PDINFO :
- buf += 6;
- break;
+ case DIRPBIT_PDINFO :
+ buf += 6;
+ break;
- default :
- err = AFPERR_BITMAP;
- goto setdirparam_done;
- break;
+ default :
+ err = AFPERR_BITMAP;
+ goto setdirparam_done;
+ break;
+ }
+
+ bitmap = bitmap>>1;
+ bit++;
}
- bitmap = bitmap>>1;
- bit++;
-}
+setdirparam_done:
+ if (change_mdate && newdate == 0 && gettimeofday(&tv, NULL) == 0) {
+ newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
+ }
+ if (newdate) {
+ if (isad)
+ ad_setdate(&ad, AD_DATE_MODIFY, newdate);
+ ut.actime = ut.modtime = AD_DATE_TO_UNIX(newdate);
+ utime(upath, &ut);
+ }
+ if ( isad ) {
+ ad_flush( &ad, ADFLAGS_HF );
+ ad_close( &ad, ADFLAGS_HF );
+ }
-setdirparam_done:
-if ( isad ) {
- ad_flush( &ad, ADFLAGS_HF );
- ad_close( &ad, ADFLAGS_HF );
-}
+ if (change_parent_mdate && curdir->d_did != DIRDID_ROOT
+ && gettimeofday(&tv, NULL) == 0) {
+ if (!movecwd(vol, curdir->d_parent)) {
+ newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
+ bitmap = 1<<DIRPBIT_MDATE;
+ setdirparams(vol, "", bitmap, (char *)&newdate);
+ /* should we reset curdir ?*/
+ }
+ }
-#ifdef FORCE_UIDGID
-restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
-return err;
+ return err;
}
int afp_createdir(obj, ibuf, ibuflen, rbuf, rbuflen )
char *path, *upath;
u_int32_t did;
u_int16_t vid;
-#ifdef FORCE_UIDGID
- uidgidset *uidgid;
-
- memset(&uidgid, 0, sizeof(uidgid));
-#endif /* FORCE_UIDGID */
*rbuflen = 0;
ibuf += 2;
memcpy( &did, ibuf, sizeof( did ));
ibuf += sizeof( did );
- if (( dir = dirsearch( vol, did )) == NULL ) {
+ if (( dir = dirlookup( vol, did )) == NULL ) {
return( AFPERR_NOOBJ );
}
}
}
-#ifdef FORCE_UIDGID
- save_uidgid ( &uidgid );
- set_uidgid ( vol );
-#endif /* FORCE_UIDGID */
-
if ( ad_mkdir( upath, DIRBITS | 0777 ) < 0 ) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
switch ( errno ) {
case ENOENT :
return( AFPERR_NOOBJ );
}
if (stat(upath, &st) < 0) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_MISC;
}
if ((dir = adddir( vol, curdir, path, strlen( path ), upath,
strlen(upath), &st)) == NULL) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_MISC;
}
if ( movecwd( vol, dir ) < 0 ) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_PARAM );
}
O_RDWR|O_CREAT, 0666, &ad ) < 0) {
if (vol_noadouble(vol))
goto createdir_done;
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_ACCESS );
}
memcpy( rbuf, &dir->d_did, sizeof( u_int32_t ));
*rbuflen = sizeof( u_int32_t );
setvoltime(obj, vol );
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFP_OK );
}
DIR *dp;
struct adouble ad;
u_int16_t ashort;
-#ifdef FORCE_UIDGID
- uidgidset *uidgid;
-
- memset(&uidgid, 0, sizeof(uidgid));
-#endif /* FORCE_UIDGID */
if ( curdir->d_parent == NULL ) {
return( AFPERR_ACCESS );
fdir = curdir;
-#ifdef FORCE_UIDGID
- save_uidgid ( &uidgid );
- set_uidgid ( vol );
-#endif /* FORCE_UIDGID */
-
memset(&ad, 0, sizeof(ad));
if ( ad_open( ".", ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
DIRBITS | 0777, &ad) == 0 ) {
ad_getattr(&ad, &ashort);
ad_close( &ad, ADFLAGS_HF );
if ((ashort & htons(ATTRBIT_NODELETE))) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_OLOCK;
}
}
* note: this will not fail with dangling symlinks */
if (stat(de->d_name, &st) == 0) {
closedir(dp);
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_DIRNEMPT;
}
switch (errno) {
case EPERM:
case EACCES :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_ACCESS );
case EROFS:
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_VLOCK;
case ENOENT :
continue;
default :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_PARAM );
}
}
case ENOENT :
break;
case ENOTEMPTY :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_DIRNEMPT );
case EROFS:
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_VLOCK;
case EPERM:
case EACCES :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_ACCESS );
default :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_PARAM );
}
}
/* bail if it's not a symlink */
if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_DIRNEMPT;
}
switch (errno) {
case EPERM:
case EACCES :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_ACCESS );
case EROFS:
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_VLOCK;
case ENOENT :
continue;
default :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_PARAM );
}
}
}
if ( movecwd( vol, curdir->d_parent ) < 0 ) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_NOOBJ );
}
if ( rmdir(mtoupath(vol, fdir->d_name)) < 0 ) {
switch ( errno ) {
case ENOENT :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_NOOBJ );
case ENOTEMPTY :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_DIRNEMPT );
case EPERM:
case EACCES :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_ACCESS );
case EROFS:
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_VLOCK;
default :
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFPERR_PARAM );
}
}
#endif /* CNID_DB */
dir_remove( vol, fdir );
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return( AFP_OK );
}
memcpy( &did, ibuf, sizeof( did ));
ibuf += sizeof( did );
- if (( dir = dirsearch( vol, did )) == NULL ) {
+ if (( dir = dirlookup( vol, did )) == NULL ) {
return( AFPERR_PARAM );
}
char *path, *upath;
u_int32_t did;
u_int16_t vid;
-#ifdef FORCE_UIDGID
- uidgidset *uidgid;
-
- memset(&uidgid, 0, sizeof(uidgid));
-#endif /* FORCE_UIDGID */
*rbuflen = 0;
ibuf += 2;
memcpy(&did, ibuf, sizeof(did));
ibuf += sizeof(did);
- if (( parentdir = dirsearch( vol, did )) == NULL ) {
+ if (( parentdir = dirlookup( vol, did )) == NULL ) {
return( AFPERR_NOOBJ );
}
dir = (dir == parentdir->d_child->d_prev) ? NULL : dir->d_next;
}
-#ifdef FORCE_UIDGID
- save_uidgid ( &uidgid );
- set_uidgid ( vol );
-#endif /* FORCE_UIDGID */
-
/* we don't already have a did. add one in. */
if ((dir = adddir(vol, parentdir, path, strlen(path),
upath, strlen(upath), &st)) == NULL) {
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFPERR_MISC;
}
memcpy(rbuf, &dir->d_did, sizeof(dir->d_did));
*rbuflen = sizeof(dir->d_did);
-#ifdef FORCE_UIDGID
- restore_uidgid ( &uidgid );
-#endif /* FORCE_UIDGID */
return AFP_OK;
}