]> arthur.barton.de Git - netatalk.git/commitdiff
better handling for file without read access.
authordidg <didg>
Mon, 10 May 2004 18:40:31 +0000 (18:40 +0000)
committerdidg <didg>
Mon, 10 May 2004 18:40:31 +0000 (18:40 +0000)
12 files changed:
etc/afpd/catsearch.c
etc/afpd/desktop.c
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/fork.h
etc/afpd/ofork.c
etc/afpd/unix.c
etc/afpd/unix.h
include/atalk/adouble.h
libatalk/adouble/ad_open.c

index 4a3a1ef23932e9b6812951e71abf0e0f2f3a8a62..72a1c685e31377795eb187c3aa60a015636844fa 100644 (file)
@@ -254,7 +254,7 @@ static struct adouble *adl_lkup(struct vol *vol, struct path *path)
                adp = &ad;
        } 
 
-       if ( ad_open( path->u_name, ADFLAGS_HF | ((isdir)?ADFLAGS_DIR:0), O_RDONLY, 0, adp) < 0 ) {
+       if ( ad_metadata( path->u_name, ((isdir)?ADFLAGS_DIR:0), adp) < 0 ) {
                return NULL;
        } 
        return adp;     
index fdeb54fc248ec1a260fb37a9aa9619798cf8be64..3da91988a894e8db006d42c43944815b53076660 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: desktop.c,v 1.26.2.4.2.13 2004-05-04 15:38:24 didg Exp $
+ * $Id: desktop.c,v 1.26.2.4.2.14 2004-05-10 18:40:32 didg Exp $
  *
  * See COPYRIGHT.
  *
@@ -807,9 +807,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rb
     } else
         adp = of->of_ad;
         
-    if ( ad_open( upath,
-                  ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
-                  O_RDONLY, 0666, adp) < 0 ) {
+    if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
         return( AFPERR_NOITEM );
     }
 
index 239a1de2a933804cb3f2e79b5ca0c89c5538f70a..c1b1cd0fb756d09509900f825689e93aeaea36e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.71.2.4.2.13 2004-05-04 15:38:24 didg Exp $
+ * $Id: directory.c,v 1.71.2.4.2.14 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -121,7 +121,7 @@ u_int32_t   did;
 #ifdef ATACC
 int path_isadir(struct path *o_path)
 {
-    return o_path->dir != NULL;
+    return o_path->d_dir != NULL;
 #if 0
     return o_path->m_name == '\0' || /* we are in a it */
            !o_path->st_valid ||      /* in cache but we can't chdir in it */ 
@@ -565,7 +565,7 @@ struct path *path;
     if ( path->u_name == NULL) {
         path->u_name = mtoupath(vol, path->m_name, dir->d_did, (path->m_type==3) );
     }
-    path->dir = NULL;
+    path->d_dir = NULL;
 
     if ( path->u_name == NULL) {
         afp_errno = AFPERR_PARAM;
@@ -598,7 +598,7 @@ struct path *path;
         }
     }
 
-    path->dir = dir;
+    path->d_dir = dir;
     if ( movecwd( vol, dir ) < 0 ) {
         return( NULL );
     }
@@ -1013,7 +1013,7 @@ char      **cpath;
     ret.m_name = path;
     ret.st_errno = 0;
     ret.st_valid = 0;
-    ret.dir = NULL;
+    ret.d_dir = NULL;
     for ( ;; ) {
         if ( len == 0 ) {
             if (movecwd( vol, dir ) < 0 ) {
@@ -1034,7 +1034,7 @@ char      **cpath;
                    */
                    ret.m_name = dir->d_m_name;
                    ret.u_name = dir->d_u_name;
-                   ret.dir = dir;
+                   ret.d_dir = dir;
                    return &ret;
                } else if (afp_errno == AFPERR_NOOBJ) {
                     if ( movecwd( vol, dir->d_parent ) < 0 ) {
@@ -1064,7 +1064,7 @@ char      **cpath;
             }
             if (*path == '\0') {
                ret.u_name = ".";
-               ret.dir = dir;
+               ret.d_dir = dir;
             }               
             return &ret;
         } /* if (len == 0) */
@@ -1303,8 +1303,7 @@ int getdirparams(const struct vol *vol,
                   (1 << DIRPBIT_FINFO)))) {
 
         ad_init(&ad, vol->v_adouble);
-       if ( !ad_open( upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
-                  DIRBITS | 0777, &ad)) {
+       if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) {
             isad = 1;
         }
     }
@@ -1484,8 +1483,7 @@ int getdirparams(const struct vol *vol,
             *data++ = ma.ma_group;
             *data++ = ma.ma_owner;
             break;
-
-
+            
         default :
             if ( isad ) {
                 ad_close( &ad, ADFLAGS_HF );
@@ -1521,7 +1519,7 @@ int path_error(struct path *path, int error)
  */
     if (path_isadir(path))
         return afp_errno;
-    if (path->st_errno)
+    if (path->st_valid && path->st_errno)
         return error;
     return AFPERR_BADTYPE ;
 }
@@ -1567,7 +1565,10 @@ int              ibuflen, *rbuflen;
     }
 
     if ( *path->m_name != '\0' ) {
-       return path_error(path, AFPERR_NOOBJ);
+        rc = path_error(path, AFPERR_NOOBJ);
+        /* maybe we are trying to set perms back */
+        if (rc != AFPERR_ACCESS)
+            return rc;
     }
 
     /*
@@ -1597,8 +1598,23 @@ struct path Cur_Path = {
     0,  /* */
 };
 
+/* ------------------ */
+static int set_dir_errors(struct path *path, const char *where, int err)
+{
+    switch ( err ) {
+    case EPERM :
+    case EACCES :
+        return AFPERR_ACCESS;
+    case EROFS :
+        return AFPERR_VLOCK;
+    }
+    LOG(log_error, logtype_afpd, "setdirparam(%s): %s: %s", fullpathname(path->u_name), where, strerror(err) );
+    return AFPERR_PARAM;
+}
+/* ------------------ */
 int setdirparams(const struct vol *vol, 
-                 struct path *path, u_int16_t bitmap, char *buf )
+                 struct path *path, u_int16_t d_bitmap, char *buf )
 {
     struct maccess     ma;
     struct adouble     ad;
@@ -1606,14 +1622,126 @@ int setdirparams(const struct vol *vol,
     struct timeval      tv;
 
     char                *upath;
-    int                        bit = 0, aint, isad = 1;
+    struct dir          *dir;
+    int                        bit, aint, isad = 1;
+    int                 cdate, bdate;
+    int                 owner, group;
     u_int16_t          ashort, bshort;
     int                 err = AFP_OK;
     int                 change_mdate = 0;
     int                 change_parent_mdate = 0;
     int                 newdate = 0;
+    u_int16_t           bitmap = d_bitmap;
+    u_char              finder_buf[32];
+    u_int32_t          upriv;
+    mode_t              mpriv;
+    u_int16_t           upriv_bit = 0;
 
+    bit = 0;
     upath = path->u_name;
+    dir   = path->d_dir;
+    while ( bitmap != 0 ) {
+        while (( bitmap & 1 ) == 0 ) {
+            bitmap = bitmap>>1;
+            bit++;
+        }
+
+        switch( bit ) {
+        case DIRPBIT_ATTR :
+            change_mdate = 1;
+            memcpy( &ashort, buf, sizeof( ashort ));
+            if ((ashort & htons(ATTRBIT_INVISIBLE)))
+               change_parent_mdate = 1;
+            buf += sizeof( ashort );
+            break;
+        case DIRPBIT_CDATE :
+            change_mdate = 1;
+            memcpy(&cdate, buf, sizeof(cdate));
+            buf += sizeof( cdate );
+            break;
+        case DIRPBIT_MDATE :
+            memcpy(&newdate, buf, sizeof(newdate));
+            buf += sizeof( newdate );
+            break;
+        case DIRPBIT_BDATE :
+            change_mdate = 1;
+            memcpy(&bdate, buf, sizeof(bdate));
+            buf += sizeof( bdate );
+            break;
+        case DIRPBIT_FINFO :
+            change_mdate = 1;
+            memcpy( finder_buf, buf, 32 );
+            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 :
+            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 );
+            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
+           report nothing amiss. <shirsch@ibm.net> */
+        case DIRPBIT_PDINFO :
+            if (afp_version < 30) {
+                buf += 6;
+            }
+            else {
+                err = AFPERR_BITMAP;
+                bitmap = 0;
+            }
+            break;
+       case DIRPBIT_UNIXPR :
+           if (vol_unix_priv(vol)) {
+               /* Skip UID and GID for now, there seems to be no way to set them from an OSX client anyway */
+                buf += sizeof( aint );
+                buf += sizeof( aint );
+
+                change_mdate = 1;
+                change_parent_mdate = 1;
+                memcpy( &upriv, buf, sizeof( upriv ));
+                buf += sizeof( upriv );
+                upriv = ntohl (upriv);
+                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, "setdirmode", errno);
+                    }
+                }
+                else {
+                    /* do it later */
+                   upriv_bit = 1;
+                }
+                break;
+            }
+            /* fall through */
+        default :
+            err = AFPERR_BITMAP;
+            bitmap = 0;
+            break;
+        }
+
+        bitmap = bitmap>>1;
+        bit++;
+    }
     ad_init(&ad, vol->v_adouble);
 
     if (ad_open( upath, vol_noadouble(vol)|ADFLAGS_HF|ADFLAGS_DIR,
@@ -1626,8 +1754,9 @@ int setdirparams(const struct vol *vol,
          * note: we also don't need to worry about mdate. also, be quiet
          *       if we're using the noadouble option.
          */
-        if (!vol_noadouble(vol) && (bitmap &
-                                    ~((1<<DIRPBIT_ACCESS)|(1<<DIRPBIT_UID)|(1<<DIRPBIT_GID)|
+        if (!vol_noadouble(vol) && (d_bitmap &
+                                    ~((1<<DIRPBIT_ACCESS)|(1<<DIRPBIT_UNIXPR)|
+                                      (1<<DIRPBIT_UID)|(1<<DIRPBIT_GID)|
                                       (1<<DIRPBIT_MDATE)|(1<<DIRPBIT_PDINFO)))) {
             return AFPERR_ACCESS;
         }
@@ -1643,6 +1772,8 @@ int setdirparams(const struct vol *vol,
         }
     }
 
+    bit = 0;
+    bitmap = d_bitmap;
     while ( bitmap != 0 ) {
         while (( bitmap & 1 ) == 0 ) {
             bitmap = bitmap>>1;
@@ -1651,9 +1782,7 @@ int setdirparams(const struct vol *vol,
 
         switch( bit ) {
         case DIRPBIT_ATTR :
-            change_mdate = 1;
             if (isad) {
-                memcpy( &ashort, buf, sizeof( ashort ));
                 ad_getattr(&ad, &bshort);
                 if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
                     bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
@@ -1661,250 +1790,114 @@ int setdirparams(const struct vol *vol,
                     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);
+                ad_setdate(&ad, AD_DATE_CREATE, cdate);
             }
-            buf += sizeof( aint );
             break;
-
         case DIRPBIT_MDATE :
-            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);
+                ad_setdate(&ad, AD_DATE_BACKUP, bdate);
             }
-            buf += sizeof( 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
-             * with the root of a volume, are the directory's
-             * location information. This eliminates that annoying
-             * behavior one sees when mounting above another mount
-             * point.
-             */
             if (isad) {
-                if (  curdir->d_did == DIRDID_ROOT ) {
-                    memcpy( ad_entry( &ad, ADEID_FINDERI ), buf, 10 );
-                    memcpy( ad_entry( &ad, ADEID_FINDERI ) + 14, buf + 14, 18 );
+                if (  dir->d_did == DIRDID_ROOT ) {
+                    /*
+                     * Alright, we admit it, this is *really* sick!
+                     * The 4 bytes that we don't copy, when we're dealing
+                     * with the root of a volume, are the directory's
+                     * location information. This eliminates that annoying
+                     * behavior one sees when mounting above another mount
+                     * point.
+                     */
+                    memcpy( ad_entry( &ad, ADEID_FINDERI ), finder_buf, 10 );
+                    memcpy( ad_entry( &ad, ADEID_FINDERI ) + 14, finder_buf + 14, 18 );
                 } else {
-                    memcpy( ad_entry( &ad, ADEID_FINDERI ), buf, 32 );
+                    memcpy( ad_entry( &ad, ADEID_FINDERI ), finder_buf, 32 );
                 }
             }
-            buf += 32;
             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) &&
-                    (setdeskowner( ntohl(aint), -1 ) < 0)) {
-                switch ( errno ) {
-                case EPERM :
-                case EACCES :
-                    err = AFPERR_ACCESS;
-                    goto setdirparam_done;
-                    break;
-                case EROFS :
-                    err = AFPERR_VLOCK;
-                    goto setdirparam_done;
-                    break;
-                default :
-                    LOG(log_error, logtype_afpd, "setdirparam(%s): setdeskowner: %s",
-                        path->u_name, strerror(errno) );
-                    if (!isad) {
-                        err = AFPERR_PARAM;
-                        goto setdirparam_done;
-                    }
-                    break;
+            if ( (dir->d_did == DIRDID_ROOT) &&
+                    (setdeskowner( ntohl(owner), -1 ) < 0)) {
+                err = set_dir_errors(path, "setdeskowner", errno);
+                if (isad && err == AFPERR_PARAM) {
+                    err = AFP_OK; /* ???*/
                 }
-            }
-            if ( setdirowner(vol,  ntohl(aint), -1 ) < 0 ) {
-                switch ( errno ) {
-                case EPERM :
-                case EACCES :
-                    err = AFPERR_ACCESS;
-                    goto setdirparam_done;
-                    break;
-                case EROFS :
-                    err = AFPERR_VLOCK;
+                else {
                     goto setdirparam_done;
-                    break;
-                default :
-                    LOG(log_error, logtype_afpd, "setdirparam(%s): setdirowner: %s",
-                        path->u_name, strerror(errno) );
-                    break;
                 }
             }
+            if ( setdirowner(vol, upath, ntohl(owner), -1 ) < 0 ) {
+                err = set_dir_errors(path, "setdirowner", errno);
+                goto setdirparam_done;
+            }
             break;
+
         case DIRPBIT_GID :
-            change_parent_mdate = 1;
-            memcpy( &aint, buf, sizeof( aint ));
-            buf += sizeof( aint );
-            if (curdir->d_did == DIRDID_ROOT)
-                setdeskowner( -1, ntohl(aint) );
+            if (dir->d_did == DIRDID_ROOT)
+                setdeskowner( -1, ntohl(group) ); 
 
 #if 0       /* don't error if we can't set the desktop owner. */
-            switch ( errno ) {
-            case EPERM :
-            case EACCES :
-                err = AFPERR_ACCESS;
-                goto setdirparam_done;
-                break;
-            case EROFS :
-                err = AFPERR_VLOCK;
-                goto setdirparam_done;
-                break;
-            default :
-                LOG(log_error, logtype_afpd, "setdirparam(%s): setdeskowner: %s", path->u_name, strerror(errno)  );
-                if (!isad) {
-                    err = AFPERR_PARAM;
+                err = set_dir_errors(path, "setdeskowner", errno);
+                if (isad && err == AFPERR_PARAM) {
+                    err = AFP_OK; /* ???*/
+                }
+                else {
                     goto setdirparam_done;
                 }
-                break;
-            }
 #endif /* 0 */
 
-            if ( setdirowner(vol, -1, ntohl(aint) ) < 0 ) {
-                switch ( errno ) {
-                case EPERM :
-                case EACCES :
-                    err = AFPERR_ACCESS;
-                    goto setdirparam_done;
-                    break;
-                case EROFS :
-                    err = AFPERR_VLOCK;
-                    goto setdirparam_done;
-                    break;
-                default :
-                    LOG(log_error, logtype_afpd, "setdirparam(%s): setdirowner: %s",
-                        path->u_name, strerror(errno) );
-                    break;
-                }
+            if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) {
+                err = set_dir_errors(path, "setdirowner", errno);
+                goto setdirparam_done;
             }
             break;
 
         case DIRPBIT_ACCESS :
-            change_mdate = 1;
-            change_parent_mdate = 1;
-            ma.ma_user = *buf++;
-            ma.ma_world = *buf++;
-            ma.ma_group = *buf++;
-            ma.ma_owner = *buf++;
-
-            if (curdir->d_did == DIRDID_ROOT)
-                setdeskmode(mtoumode( &ma ));
-#if 0 /* don't error if we can't set the desktop mode */
-            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(%s): setdeskmode: %s",
-                    path->u_name, strerror(errno) );
-                break;
-                err = AFPERR_PARAM;
-                goto setdirparam_done;
-            }
-#endif /* 0 */
-
-            if ( setdirmode( vol, mtoumode( &ma )) < 0 ) {
-                switch ( errno ) {
-                case EPERM :
-                case EACCES :
+            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 setdirparam_done;
-                case EROFS :
-                    err = AFPERR_VLOCK;
-                    goto setdirparam_done;
-                default :
-                    LOG(log_error, logtype_afpd, "setdirparam(%s): setdirmode: %s",
-                        path->u_name, strerror(errno) );
-                    err = AFPERR_PARAM;
-                    goto setdirparam_done;
                 }
             }
-            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 :
-            if (afp_version < 30) {
-                buf += 6;
-                break;
-            }
 
-       case DIRPBIT_UNIXPR :
-           /* Skip UID and GID for now, there seems to be now way to set them from an OSX client anyway */
-            buf += sizeof( aint );
-            buf += sizeof( aint );
-
-            change_mdate = 1;
-            change_parent_mdate = 1;
-            memcpy( &aint, buf, sizeof( aint ));
-            buf += sizeof( aint );
-           aint = ntohl (aint);
-            if (curdir->d_did == DIRDID_ROOT)
-                setdeskmode( aint );
-#if 0 /* don't error if we can't set the desktop mode */
-            switch ( errno ) {
-            case EPERM :
-            case EACCES :
-                err = AFPERR_ACCESS;
-                goto setdirparam_done;
-            case EROFS :
-                err = AFPERR_VLOCK;
+            if (!dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) {
+                err = set_dir_errors(path, "setdirmode", errno);
                 goto setdirparam_done;
-            default :
-                LOG(log_error, logtype_afpd, "setdirparam(%s): setdeskmode: %s",
-                    path->u_name, strerror(errno) );
-                break;
-                err = AFPERR_PARAM;
+            }
+            break;
+        case DIRPBIT_PDINFO :
+            if (afp_version >= 30) {
+                err = AFPERR_BITMAP;
                 goto setdirparam_done;
             }
-#endif /* 0 */
+            break;
+       case DIRPBIT_UNIXPR :
+           if (vol_unix_priv(vol)) {
+                if (dir->d_did == DIRDID_ROOT) {
+                    setdeskmode( upriv );
+                    if (!dir_rx_set(upriv)) {
+                        /* we can't remove read and search for owner on volume root */
+                        err = AFPERR_ACCESS;
+                        goto setdirparam_done;
+                    }
+                }
 
-            if ( setdirunixmode(vol, aint) < 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(%s): setdirmode: %s",
-                        path->u_name, strerror(errno) );
-                    err = AFPERR_PARAM;
+                if ( upriv_bit && setdirunixmode(vol, upath, upriv) < 0 ) {
+                    err = set_dir_errors(path, "setdirmode", errno);
                     goto setdirparam_done;
                 }
+                break;
             }
-            break;
-
+            /* fall through */
         default :
             err = AFPERR_BITMAP;
             goto setdirparam_done;
@@ -1930,20 +1923,20 @@ setdirparam_done:
         if (path->st_valid && !path->st_errno) {
             struct stat *st = &path->st;
 
-            if (curdir->d_parent) {
+            if (dir && dir->d_parent) {
                 ad_setid(&ad,(vol->v_flags & AFPVOL_NODEV)?0:st->st_dev, 
-                         st->st_ino,  curdir->d_did, curdir->d_parent->d_did, vol->v_stamp);
+                         st->st_ino,  dir->d_did, dir->d_parent->d_did, vol->v_stamp);
             }
         }
-    
         ad_flush( &ad, ADFLAGS_HF );
         ad_close( &ad, ADFLAGS_HF );
     }
 
-    if (change_parent_mdate && curdir->d_did != DIRDID_ROOT
+    if (change_parent_mdate && dir->d_did != DIRDID_ROOT
             && gettimeofday(&tv, NULL) == 0) {
-       if (!movecwd(vol, curdir->d_parent)) {
+       if (!movecwd(vol, dir->d_parent)) {
            newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
+           /* be careful with bitmap because now dir is null */
            bitmap = 1<<DIRPBIT_MDATE;
            setdirparams(vol, &Cur_Path, bitmap, (char *)&newdate);
            /* should we reset curdir ?*/
@@ -2160,8 +2153,7 @@ int pathlen;
     fdir = curdir;
 
     ad_init(&ad, vol->v_adouble);
-    if ( ad_open( ".", ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
-                  DIRBITS | 0777, &ad) == 0 ) {
+    if ( ad_metadata( ".", ADFLAGS_DIR, &ad) == 0 ) {
 
         ad_getattr(&ad, &ashort);
         ad_close( &ad, ADFLAGS_HF );
index f9113b237bdadf3c2e7b4e7e1484a2ffff5580be..35971bf468d8d7eef13d12ef645174ba6aa234ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.h,v 1.13.2.4.2.1 2004-03-11 02:01:59 didg Exp $
+ * $Id: directory.h,v 1.13.2.4.2.2 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -63,7 +63,7 @@ struct path {
     int         m_type;             /* mac name type (long name, unicode */
     char       *m_name;            /* mac name */
     char        *u_name;            /* unix name */
-    struct dir  *dir;               /* */
+    struct dir  *d_dir;             /* */
     int         st_valid;           /* does st_errno and st set */
     int         st_errno;
     struct stat st;
@@ -72,7 +72,7 @@ struct path {
 #ifndef ATACC
 static __inline__ int path_isadir(struct path *o_path)
 {
-    return o_path->dir != NULL;
+    return o_path->d_dir != NULL;
 #if 0
     return o_path->m_name == '\0' || /* we are in a it */
            !o_path->st_valid ||      /* in cache but we can't chdir in it */ 
index d903305e1be60447038c3cbdd37c778dbbcee3fb..d6ba3e01e32c6641581c23ec25248f6a3393a138 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.92.2.2.2.24 2004-05-04 15:38:24 didg Exp $
+ * $Id: file.c,v 1.92.2.2.2.25 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -454,7 +454,7 @@ int getmetadata(struct vol *vol,
             memcpy(data, &aint, sizeof( aint ));
             data += sizeof( aint );
             break;
-        case FILPBIT_UNIXPR :
+        case FILPBIT_UNIXPR :            
             /* accessmode may change st_mode with ACLs */
             accessmode( upath, &ma, dir , st);
 
@@ -469,13 +469,12 @@ int getmetadata(struct vol *vol,
             memcpy( data, &aint, sizeof( aint ));
             data += sizeof( aint );
 
-
             *data++ = ma.ma_user;
             *data++ = ma.ma_world;
             *data++ = ma.ma_group;
             *data++ = ma.ma_owner;
             break;
-
+            
         default :
             return( AFPERR_BITMAP );
         }
@@ -526,10 +525,22 @@ int getfilparams(struct vol *vol,
             adp = &ad;
         }
 
-        if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
-             adp = NULL;
+        if ( ad_metadata( upath, 0, adp) < 0 ) {
+            switch (errno) {
+            case EACCES:
+                LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
+                upath, strerror(errno));
+                return AFPERR_ACCESS;
+            case EIO:
+                LOG(log_error, logtype_afpd, "getfilparams(%s): bad resource fork", upath);
+                /* fall through */
+            case ENOENT:
+            default:
+                adp = NULL;
+                break;
+            }
         }
-        else {
+        if (adp) {
            /* FIXME 
               we need to check if the file is open by another process.
               it's slow so we only do it if we have to:
@@ -752,21 +763,24 @@ int               ibuflen, *rbuflen;
 
 /*
  * cf AFP3.0.pdf page 252 for change_mdate and change_parent_mdate logic  
- *
+ * 
 */
 extern struct path Cur_Path;
 
 int setfilparams(struct vol *vol,
-                 struct path *path, u_int16_t bitmap, char *buf )
+                 struct path *path, u_int16_t f_bitmap, char *buf )
 {
     struct adouble     ad, *adp;
     struct ofork        *of;
     struct extmap      *em;
-    int                        bit = 0, isad = 1, err = AFP_OK;
+    int                        bit, isad = 1, err = AFP_OK;
     char                *upath;
     u_char              achar, *fdType, xyy[4];
     u_int16_t          ashort, bshort;
     u_int32_t          aint;
+    u_int32_t          upriv;
+    u_int16_t           upriv_bit = 0;
+    
     struct utimbuf     ut;
 
     int                 change_mdate = 0;
@@ -775,7 +789,9 @@ int setfilparams(struct vol *vol,
     struct timeval      tv;
     uid_t              f_uid;
     gid_t              f_gid;
-
+    u_int16_t           bitmap = f_bitmap;
+    u_int32_t           cdate,bdate;
+    u_char              finder_buf[32];
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin setfilparams:");
@@ -793,78 +809,47 @@ int setfilparams(struct vol *vol,
         return AFPERR_ACCESS;
     }
 
-    if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
-                 O_RDWR|O_CREAT, 0666, adp) < 0) {
-        /* for some things, we don't need an adouble header */
-        if (bitmap & ~(1<<FILPBIT_MDATE)) {
-            return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
-        }
-        isad = 0;
-    } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
-        ad_setname(adp, path->m_name);
-    }
-
+    /* with unix priv maybe we have to change adouble file priv first */
+    bit = 0;
     while ( bitmap != 0 ) {
         while (( bitmap & 1 ) == 0 ) {
             bitmap = bitmap>>1;
             bit++;
         }
-
         switch(  bit ) {
         case FILPBIT_ATTR :
             change_mdate = 1;
             memcpy(&ashort, buf, sizeof( ashort ));
-            ad_getattr(adp, &bshort);
-            if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
-                bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
-            } else {
-                bshort &= ~ashort;
-            }
             if ((ashort & htons(ATTRBIT_INVISIBLE)))
                 change_parent_mdate = 1;
-            ad_setattr(adp, bshort);
             buf += sizeof( ashort );
             break;
-
         case FILPBIT_CDATE :
             change_mdate = 1;
-            memcpy(&aint, buf, sizeof(aint));
-            ad_setdate(adp, AD_DATE_CREATE, aint);
-            buf += sizeof( aint );
+            memcpy(&cdate, buf, sizeof(cdate));
+            buf += sizeof( cdate );
             break;
-
         case FILPBIT_MDATE :
             memcpy(&newdate, buf, sizeof( newdate ));
             buf += sizeof( newdate );
             break;
-
         case FILPBIT_BDATE :
             change_mdate = 1;
-            memcpy(&aint, buf, sizeof(aint));
-            ad_setdate(adp, AD_DATE_BACKUP, aint);
-            buf += sizeof( aint );
+            memcpy(&bdate, buf, sizeof( bdate));
+            buf += sizeof( bdate );
             break;
-
         case FILPBIT_FINFO :
             change_mdate = 1;
-
-            if (!memcmp( ad_entry( adp, ADEID_FINDERI ), ufinderi, 8 )
-                    && ( 
-                     ((em = getextmap( path->m_name )) &&
-                      !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
-                      !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
-                     || ((em = getdefextmap()) &&
-                      !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
-                      !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
-            )) {
-                memcpy(buf, ufinderi, 8 );
-            }
-
-            memcpy(ad_entry( adp, ADEID_FINDERI ), buf, 32 );
+            memcpy(finder_buf, buf, 32 );
             buf += 32;
             break;
-
         case FILPBIT_UNIXPR :
+            if (!vol_unix_priv(vol)) {
+               /* this volume doesn't use unix priv */
+               err = AFPERR_BITMAP;
+               bitmap = 0;
+               break;
+            }
             change_mdate = 1;
             change_parent_mdate = 1;
 
@@ -876,16 +861,17 @@ int setfilparams(struct vol *vol,
             buf += sizeof( aint );
             setfilowner(vol, f_uid, f_gid, path);
 
-            memcpy( &aint, buf, sizeof( aint ));
-            buf += sizeof( aint );
-            aint = ntohl (aint);
-            setfilunixmode(vol, path, aint);
+            memcpy( &upriv, buf, sizeof( upriv ));
+            buf += sizeof( upriv );
+            upriv = ntohl (upriv);
+            if ((upriv & S_IWUSR)) {
+               setfilunixmode(vol, path, upriv);
+            }
+            else {
+               /* do it later */
+               upriv_bit = 1;
+            }
             break;
-            /* Client needs to set the ProDOS file info for this file.
-               Use a defined string for TEXT to support crlf
-               translations and convert all else into pXYY per Inside
-               Appletalk.  Always set the creator as "pdos".  Changes
-               from original by Marsha Jackson. */
         case FILPBIT_PDINFO :
             if (afp_version < 30) { /* else it's UTF8 name */
                 achar = *buf;
@@ -901,6 +887,81 @@ int setfilparams(struct vol *vol,
                    xyy[2] = *buf++;
                    fdType = xyy;
                }
+                break;
+            }
+            /* fallthrough */
+        default :
+            err = AFPERR_BITMAP;
+            /* break while loop */
+            bitmap = 0;
+            break;
+        }
+
+        bitmap = bitmap>>1;
+        bit++;
+    }
+
+    /* second try with adouble open 
+    */
+    if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
+                 O_RDWR|O_CREAT, 0666, adp) < 0) {
+        /* for some things, we don't need an adouble header */
+        if (f_bitmap & ~(1<<FILPBIT_MDATE)) {
+            return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
+        }
+        isad = 0;
+    } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
+        ad_setname(adp, path->m_name);
+    }
+    
+    bit = 0;
+    bitmap = f_bitmap;
+    while ( bitmap != 0 ) {
+        while (( bitmap & 1 ) == 0 ) {
+            bitmap = bitmap>>1;
+            bit++;
+        }
+
+        switch(  bit ) {
+        case FILPBIT_ATTR :
+            ad_getattr(adp, &bshort);
+            if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
+                bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
+            } else {
+                bshort &= ~ashort;
+            }
+            ad_setattr(adp, bshort);
+            break;
+        case FILPBIT_CDATE :
+            ad_setdate(adp, AD_DATE_CREATE, cdate);
+            break;
+        case FILPBIT_MDATE :
+            break;
+        case FILPBIT_BDATE :
+            ad_setdate(adp, AD_DATE_BACKUP, bdate);
+            break;
+        case FILPBIT_FINFO :
+            if (!memcmp( ad_entry( adp, ADEID_FINDERI ), ufinderi, 8 )
+                    && ( 
+                     ((em = getextmap( path->m_name )) &&
+                      !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) &&
+                      !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator)))
+                     || ((em = getdefextmap()) &&
+                      !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) &&
+                      !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator)))
+            )) {
+                memcpy(finder_buf, ufinderi, 8 );
+            }
+
+            memcpy(ad_entry( adp, ADEID_FINDERI ), finder_buf, 32 );
+            break;
+        case FILPBIT_UNIXPR :
+            if (upriv_bit) {
+               setfilunixmode(vol, path, upriv);
+            }
+            break;
+        case FILPBIT_PDINFO :
+            if (afp_version < 30) { /* else it's UTF8 name */
                 memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
                 memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
                 break;
@@ -910,7 +971,6 @@ int setfilparams(struct vol *vol,
             err = AFPERR_BITMAP;
             goto setfilparam_done;
         }
-
         bitmap = bitmap>>1;
         bit++;
     }
@@ -1188,9 +1248,6 @@ int               ibuflen, *rbuflen;
         return get_afp_errno(AFPERR_NOOBJ); 
     }
     if ( *s_path->m_name != '\0' ) {
-#if 0
-        return (path_isadir( s_path))? AFPERR_PARAM:AFPERR_BADTYPE ;
-#endif        
        path_error(s_path, AFPERR_PARAM);
     }
 
@@ -1426,6 +1483,7 @@ char              *file;
 int         checkAttrib;
 {
     struct adouble     ad;
+    struct adouble      *adp = &ad;
     int                        adflags, err = AFP_OK;
 
 #ifdef DEBUG
@@ -1447,7 +1505,8 @@ int         checkAttrib;
                 continue;
 
             case EACCES:
-                return AFPERR_ACCESS;
+                adp = NULL; /* maybe it's a file we no rw mode for us */
+                break;      /* was return AFPERR_ACCESS;*/
             case EROFS:
                 return AFPERR_VLOCK;
             default:
@@ -1459,17 +1518,31 @@ int         checkAttrib;
     /*
      * Does kFPDeleteInhibitBit (bit 8) set?
      */
-    if (checkAttrib && (adflags & ADFLAGS_HF)) {
+    if (checkAttrib) {
         u_int16_t   bshort;
+        
+        if (adp && (adflags & ADFLAGS_HF)) {
 
-        ad_getattr(&ad, &bshort);
-        if ((bshort & htons(ATTRBIT_NODELETE))) {
-            ad_close( &ad, adflags );
-            return(AFPERR_OLOCK);
+            ad_getattr(&ad, &bshort);
+            if ((bshort & htons(ATTRBIT_NODELETE))) {
+                ad_close( &ad, adflags );
+                return(AFPERR_OLOCK);
+            }
+        }
+        else if (!adp) {
+            /* was EACCESS error try to get only metadata */
+            ad_init(&ad, vol->v_adouble);  /* OK */
+            if ( ad_metadata( file , 0, &ad) == 0 ) {
+                ad_getattr(&ad, &bshort);
+                ad_close( &ad, ADFLAGS_HF );
+                if ((bshort & htons(ATTRBIT_NODELETE))) {
+                    return  AFPERR_OLOCK;
+                }
+            }
         }
     }
     
-    if ((adflags & ADFLAGS_HF) ) {
+    if (adp && (adflags & ADFLAGS_HF) ) {
         /* FIXME we have a pb here because we want to know if a file is open 
          * there's a 'priority inversion' if you can't open the ressource fork RW
          * you can delete it if it's open because you can't get a write lock.
@@ -1485,7 +1558,7 @@ int         checkAttrib;
         }
     }
 
-    if (ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
+    if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
         err = AFPERR_BUSY;
     }
     else if (!(err = netatalk_unlink( vol->ad_path( file, ADFLAGS_HF)) ) &&
@@ -1497,7 +1570,8 @@ int         checkAttrib;
         }
 
     }
-    ad_close( &ad, adflags );  /* ad_close removes locks if any */
+    if (adp)
+        ad_close( &ad, adflags );  /* ad_close removes locks if any */
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "end deletefile:");
index 4a456234162e8eccc501723bbd8ebdaeb7a5ea67..f5d2367b282deb3c9e0143d72656f7c7c9b85ea0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.c,v 1.45.2.2.2.10 2004-05-04 15:38:25 didg Exp $
+ * $Id: filedir.c,v 1.45.2.2.2.11 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -180,7 +180,7 @@ int         ibuflen, *rbuflen;
          * it's curdir (maybe deleted, but then we can't know).
          * So we need to try harder.
          */
-        of_statdir(s_path);
+        of_statdir(vol, s_path);
     }
     if ( s_path->st_errno != 0 ) {
         return( AFPERR_NOOBJ );
@@ -189,7 +189,7 @@ int         ibuflen, *rbuflen;
     buflen = 0;
     if (S_ISDIR(st->st_mode)) {
         if (dbitmap) {
-            dir = s_path->dir;
+            dir = s_path->d_dir;
             if (!dir) 
                 return AFPERR_NOOBJ;
 
@@ -272,7 +272,7 @@ int         ibuflen, *rbuflen;
         /* it's a dir and it should be there
          * because we chdir in it in cname
          */
-        of_stat(path);
+        of_statdir(vol, path);
     }
 
     if ( path->st_errno != 0 ) {
@@ -381,7 +381,7 @@ int         isdir;
      * we are in the dest folder so we need to use p for ad_open
     */
     
-    if (!ad_open(p, ADFLAGS_HF |adflags, O_RDONLY, 0666, adp)) {
+    if (!ad_metadata(p, adflags, adp)) {
     u_int16_t bshort;
 
         ad_getattr(adp, &bshort);
@@ -501,7 +501,7 @@ int         ibuflen, *rbuflen;
         strcpy(oldname, path->m_name); /* an extra copy for of_rename */
         if (isdir) {
             /* curdir parent dir, need to move sdir back */
-            sdir = path->dir;
+            sdir = path->d_dir;
         }
     }
     else {
@@ -712,7 +712,7 @@ int         ibuflen, *rbuflen;
     isdir = path_isadir(path);
     if ( *path->m_name != '\0' ) {
         if (isdir) {
-            sdir = path->dir;
+            sdir = path->d_dir;
        }
         strcpy(oldname, path->m_name); /* an extra copy for of_rename */
     } else {
index 3600a6e7736f88ed9e0e55581f5cc185edb1284a..2611a1ba5507f193636bac973ef5353564cbe48b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.h,v 1.8.6.1 2004-03-02 13:27:08 didg Exp $
+ * $Id: fork.h,v 1.8.6.2 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -68,7 +68,7 @@ extern int          of_rename    __P((const struct vol *,
 extern int          of_flush     __P((const struct vol *));
 extern void         of_pforkdesc __P((FILE *));
 extern int          of_stat      __P((struct path *));
-extern int          of_statdir   __P((struct path *));
+extern int          of_statdir   __P((const struct vol *vol, struct path *));
 /* in fork.c */
 extern int          flushfork    __P((struct ofork *));
 
index 225f25391985f33ed43f93083afdc18144bfa9e9..1d39b26681693b2592f7f5ffd30e9c658d255940 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ofork.c,v 1.20.6.5 2004-03-02 13:27:08 didg Exp $
+ * $Id: ofork.c,v 1.20.6.6 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1996 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -286,10 +286,8 @@ int ret;
    return ret;
 }
 
-/* -------------------------- 
- * assume 
-*/
-int of_statdir  (struct path *path)
+/* -------------------------- */
+int of_statdir  (const struct vol *vol, struct path *path)
 {
 static char pathname[ MAXPATHLEN + 1];
 int ret;
@@ -300,11 +298,23 @@ int ret;
     }
     path->st_errno = 0;
     path->st_valid = 1;
+    /* FIXME, what about: we don't have r-x perm anymore ? */
     strcpy(pathname, "../");
-    strlcat(pathname, path->dir->d_u_name, MAXPATHLEN);
-    if ((ret = stat(pathname, &path->st)) < 0)
-       path->st_errno = errno;
-   return ret;
+    strlcat(pathname, path->d_dir->d_u_name, MAXPATHLEN);
+
+    if (!(ret = stat(pathname, &path->st)))
+        return 0;
+        
+    path->st_errno = errno;
+    /* hmm, can't stat curdir anymore */
+    if (errno == EACCES && curdir->d_parent ) {
+       if (movecwd(vol, curdir->d_parent)) 
+           return -1;
+       path->st_errno = 0;
+       if ((ret = stat(path->d_dir->d_u_name, &path->st)) < 0) 
+           path->st_errno = errno;
+    }
+    return ret;
 }
 
 /* -------------------------- */
index cbf79c7e852e55db224614a97ceb5d6d6a042f2f..82b84eb3d0c4dfa6e5afa7e377bf033f6f26eb63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.c,v 1.43.2.1.2.6 2004-05-08 22:39:26 didg Exp $
+ * $Id: unix.c,v 1.43.2.1.2.7 2004-05-10 18:40:32 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -303,6 +303,14 @@ const int dropbox;
     return retval;
 }
 
+/* ------------------------- */
+int dir_rx_set(mode_t mode)
+{
+    return (mode & (S_IXUSR | S_IRUSR)) == (S_IXUSR | S_IRUSR);
+}
+
+#define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH)
+
 int setdeskmode( mode )
 const mode_t   mode;
 {
@@ -312,6 +320,10 @@ const mode_t       mode;
     struct dirent      *deskp, *subp;
     DIR                        *desk, *sub;
 
+    if (!dir_rx_set(mode)) {
+        /* want to remove read and search access to owner it will screw the volume */
+        return -1 ;
+    }
     if ( getcwd( wd , MAXPATHLEN) == NULL ) {
         return( -1 );
     }
@@ -350,9 +362,9 @@ const mode_t        mode;
 
             if (S_ISDIR(st.st_mode)) {
                 if ( chmod( modbuf,  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
-                    LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
+                     LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
                 }
-            } else if ( chmod( modbuf,  mode & ~default_options.umask ) < 0 && errno != EPERM ) {
+            } else if ( chmod( modbuf,  mode & ~(default_options.umask | EXEC_MODE) ) < 0 && errno != EPERM ) {
                 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
             }
 
@@ -418,25 +430,44 @@ mode_t mask = S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH;
 }
 
 /* --------------------- */
-int setdirunixmode( vol, mode )
+int setdirunixmode( vol, name, mode )
 const struct vol *vol;
+const char       *name;
 const mode_t     mode;
 {
+char *adouble = vol->ad_path( name, ADFLAGS_DIR );
+
     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 (dir_rx_set(mode)) {
+       /* extending right? dir first then .AppleDouble */
+       if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
+               return -1;
+       if (vol->v_adouble != AD_VERSION2_OSX) {
+            if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
+                return  -1 ;
+            }
+        }
+    }
+    if (setfilmode(adouble, ad_hf_mode(mode), NULL) < 0 && !vol_noadouble(vol)) {
+        return  -1 ;
+    }
+    if (!dir_rx_set(mode)) {
+       if (vol->v_adouble != AD_VERSION2_OSX) {
+            if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
+                return  -1 ;
+            }
+        }
+       if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
+            return -1;
     }
-
-    if ( stickydirmode(".", DIRBITS | mode, dropbox) < 0 )
-        return -1;
     return 0;
 }
 
 /* --------------------- */
-int setdirmode( vol, mode )
+int setdirmode( vol, name, mode )
 const struct vol *vol;
+const char       *name;
 const mode_t mode;
 {
     char               buf[ MAXPATHLEN + 1];
@@ -447,9 +478,22 @@ const mode_t mode;
     int                 osx = vol->v_adouble == AD_VERSION2_OSX;
     int                 hf_mode = ad_hf_mode(mode);
     int                 dropbox = (vol->v_flags & AFPVOL_DROPBOX);
+    char                *adouble = vol->ad_path( name, ADFLAGS_DIR );
+    char                *adouble_p = ad_dir(adouble);
     
-    if (( dir = opendir( "." )) == NULL ) {
-        LOG(log_error, logtype_afpd, "setdirmode: opendir %s: %s", fullpathname("."), strerror(errno) );
+    if (dir_rx_set(mode)) {
+       /* extending right? dir first then .AppleDouble */
+       if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
+               return -1;
+       if (!osx) {
+            if (stickydirmode(adouble_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
+                return  -1 ;
+            }
+        }
+    }
+    
+    if (( dir = opendir( name )) == NULL ) {
+        LOG(log_error, logtype_afpd, "setdirmode: opendir: %s", fullpathname(name), strerror(errno) );
         return( -1 );
     }
 
@@ -472,7 +516,7 @@ const mode_t mode;
            }
         }
 #if 0
-            /* XXX: need to preserve special modes */
+        /* Don't change subdir perm */
         else if (S_ISDIR(st.st_mode)) {
                 if (stickydirmode(dirp->d_name, DIRBITS | mode, dropbox) < 0)
                     return (-1);
@@ -489,13 +533,13 @@ const mode_t mode;
     
     /* change perm of .AppleDouble's files
     */
-    if (( dir = opendir( ".AppleDouble" )) == NULL ) {
+    if (( dir = opendir( adouble_p )) == NULL ) {
         if (vol_noadouble(vol))
             goto setdirmode_noadouble;
         LOG(log_error, logtype_afpd, "setdirmode: opendir %s: %s", fullpathname(".AppleDouble"),strerror(errno) );
         return( -1 );
     }
-    strcpy( buf, ".AppleDouble" );
+    strcpy( buf, adouble_p);
     strcat( buf, "/" );
     m = strchr( buf, '\0' );
     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
@@ -518,16 +562,18 @@ const mode_t mode;
     } /* end for */
     closedir( dir );
 
-    /* XXX: use special bits to tag directory permissions */
-
-    /* XXX: need to preserve special modes */
-    if ( stickydirmode(".AppleDouble", DIRBITS | mode, dropbox) < 0 )
-        return( -1 );
+    if (!dir_rx_set(mode)) {
+        /* XXX: need to preserve special modes */
+        if (stickydirmode(adouble_p, DIRBITS | mode, dropbox) < 0 ) {
+                return  -1 ;
+        }
+    }
 
 setdirmode_noadouble:
-    /* XXX: need to preserve special modes */
-    if ( stickydirmode(".", DIRBITS | mode, dropbox) < 0 )
-        return( -1 );
+    if (!dir_rx_set(mode)) {
+       if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
+               return -1;
+    }
     return( 0 );
 }
 
@@ -639,8 +685,9 @@ struct path* path;
  * 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(vol, uid, gid )
+int setdirowner(vol, name, uid, gid )
 const struct vol *vol;
+const char      *name;
 const uid_t    uid;
 const gid_t    gid;
 {
@@ -651,8 +698,10 @@ const gid_t        gid;
     DIR                        *dir;
     int                 osx = vol->v_adouble == AD_VERSION2_OSX;
     int                 noadouble = vol_noadouble(vol);
+    char                *adouble; 
+    char                *adouble_p;
 
-    if (( dir = opendir( "." )) == NULL ) {
+    if (( dir = opendir( name )) == NULL ) {
         return( -1 );
     }
     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
@@ -678,12 +727,14 @@ const gid_t       gid;
        goto setdirowner_noadouble;
     }
 
-    if (( dir = opendir( ".AppleDouble" )) == NULL ) {
+    adouble = vol->ad_path( name, ADFLAGS_DIR );
+    adouble_p = ad_dir(adouble);
+    if (( dir = opendir( adouble_p )) == NULL ) {
         if (noadouble)
             goto setdirowner_noadouble;
         return( -1 );
     }
-    strcpy( buf, ".AppleDouble" );
+    strcpy( buf, adouble_p );
     strcat( buf, "/" );
     m = strchr( buf, '\0' );
     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
index 7cf397a1c16137307d157359cf28619dcf861727..370045d137d65c7440e02b407d417cf884476452 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.h,v 1.12.2.1.2.5 2004-05-08 22:39:26 didg Exp $
+ * $Id: unix.h,v 1.12.2.1.2.6 2004-05-10 18:40:33 didg Exp $
  */
 
 #ifndef AFPD_UNIX_H
@@ -217,14 +217,15 @@ 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 struct vol *, const mode_t));
-extern int setdirmode       __P((const struct vol *, const mode_t));
+extern int setdirunixmode   __P((const struct vol *, const char *, const mode_t));
+extern int setdirmode       __P((const struct vol *, const char *, const mode_t));
 extern int setdeskowner     __P((const uid_t, const gid_t));
-extern int setdirowner      __P((const struct vol *, const uid_t, const gid_t));
+extern int setdirowner      __P((const struct vol *, const char *, const uid_t, const gid_t));
 extern int setfilmode       __P((char *, mode_t , struct stat *));
 extern int setfilunixmode   __P((const struct vol *, struct path*, const mode_t));
 extern int setfilowner      __P((const struct vol *, const uid_t, const gid_t, struct path*));
 extern int unix_rename      __P((const char *oldpath, const char *newpath));
+extern int dir_rx_set       __P((mode_t mode));
 
 extern void accessmode      __P((char *, struct maccess *, struct dir *, struct stat *));
 extern char *fullpathname   __P((const char *));
index bcfb5dc4d8dc31cd25d6dda622afdc0d7449c123..8918898bbf560b07c2477f3623dfc9777fca10af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.21.6.16 2004-04-21 18:45:45 bfernhomberg Exp $
+ * $Id: adouble.h,v 1.21.6.17 2004-05-10 18:40:33 didg Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -372,6 +372,8 @@ 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 *));
 
+#define ad_metadata(name, flags, adp)  ad_open(name, ADFLAGS_HF|(flags), O_RDONLY, 0666, adp)
+
 /* extend header to RW if R or W (W if R for locking),
  */ 
 #ifndef ATACC
@@ -380,6 +382,9 @@ extern int ad_stat        __P((const char *, struct stat *));
 #endif
 static __inline__ mode_t ad_hf_mode (mode_t mode)
 {
+#if 1
+    mode |= S_IRUSR;
+#endif    
     /* fnctl lock need write access */
     if ((mode & S_IRUSR))
         mode |= S_IWUSR;
index 791309d477176b0ac27608aacb7a89179cd40a47..f516d58f31fa9947969dd9894709c9978ec34f7d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.30.6.12 2004-05-08 22:38:33 didg Exp $
+ * $Id: ad_open.c,v 1.30.6.13 2004-05-10 18:40:33 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -470,6 +470,8 @@ bail_err:
 #ifdef ATACC
 mode_t ad_hf_mode (mode_t mode)
 {
+    /* we always need RW mode for file owner */
+    mode |= S_IRUSR;
     /* fnctl lock need write access */
     if ((mode & S_IRUSR))
         mode |= S_IWUSR;