]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/file.c
remove gcc warnings and cleanup inline mess
[netatalk.git] / etc / afpd / file.c
index 77398bd4f6a43d3d1f435c74595f457a65601c87..efbc55ab05e30a4491795655569e00201fd7a496 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.92.2.2.2.29 2004-09-02 12:31:55 didg Exp $
+ * $Id: file.c,v 1.92.2.2.2.31.2.22 2008-11-25 15:16:33 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -68,29 +68,54 @@ char *strchr (), *strrchr ();
  *                           putawayID    4  home directory id
  */
 
-const u_char ufinderi[] = {
-                              'T', 'E', 'X', 'T', 'U', 'N', 'I', 'X',
+const u_char ufinderi[ADEDLEN_FINDERI] = {
                               0, 0, 0, 0, 0, 0, 0, 0,
+                              1, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0
                           };
 
-/* FIXME mpath : unix or mac name ? (for now it's mac name ) */
-void *get_finderinfo(const char *mpath, struct adouble *adp, void *data)
+static const u_char old_ufinderi[] = {
+                              'T', 'E', 'X', 'T', 'U', 'N', 'I', 'X'
+                          };
+
+/* ---------------------- 
+*/
+static int default_type(void *finder) 
+{
+    if (!memcmp(finder, ufinderi, 8) || !memcmp(finder, old_ufinderi, 8))
+        return 1;
+    return 0;
+}
+
+/* FIXME path : unix or mac name ? (for now it's unix name ) */
+void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data)
 {
     struct extmap      *em;
-    void                *ad_finder;
+    void                *ad_finder = NULL;
+    int                 chk_ext = 0;
+    
+    if (adp)
+        ad_finder = ad_entry(adp, ADEID_FINDERI);
 
-    if (adp && (ad_finder = ad_entry(adp, ADEID_FINDERI))) {
-        memcpy(data, ad_finder, 32);
+    if (ad_finder) {
+        memcpy(data, ad_finder, ADEDLEN_FINDERI);
+        /* default type ? */
+        if (default_type(ad_finder)) 
+            chk_ext = 1;
     }
     else {
-        memcpy(data, ufinderi, 32);
+        memcpy(data, ufinderi, ADEDLEN_FINDERI);
+        chk_ext = 1;
+        if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
+            u_int16_t ashort;
+            
+            ashort = htons(FINDERINFO_INVISIBLE);
+            memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
+        }
     }
-
-    if ((!adp  || !memcmp(ad_entry(adp, ADEID_FINDERI),ufinderi , 8 )) 
-               && (em = getextmap( mpath ))
-    ) {
+    /** Only enter if no appledouble information and no finder information found. */
+    if (chk_ext && (em = getextmap( upath ))) {
         memcpy(data, em->em_type, sizeof( em->em_type ));
         memcpy((char *)data + 4, em->em_creator, sizeof(em->em_creator));
     }
@@ -161,43 +186,22 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t
                                  (1 << FILPBIT_FINFO) |\
                                  (1 << FILPBIT_RFLEN) |\
                                  (1 << FILPBIT_EXTRFLEN) |\
-                                 (1 << FILPBIT_PDINFO)))
+                                 (1 << FILPBIT_PDINFO) |\
+                                 (1 << FILPBIT_UNIXPR)))
 
 /* -------------------------- */
 u_int32_t get_id(struct vol *vol, struct adouble *adp,  const struct stat *st,
-             const cnid_t did, const char *upath, const int len) 
+             const cnid_t did, char *upath, const int len) 
 {
 u_int32_t aint = 0;
 
 #if AD_VERSION > AD_VERSION1
-dev_t  dev;
-ino_t  ino;
-cnid_t a_did;
-char   stamp[ADEDLEN_PRIVSYN];
-    /* look in AD v2 header 
-     * note inode and device are opaques and not in network order
-    */
-    if (adp 
-           && sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)
-           && sizeof(ino_t) == ad_getentrylen(adp,ADEID_PRIVINO)
-           && sizeof(stamp) == ad_getentrylen(adp,ADEID_PRIVSYN)
-           && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_DID)
-           && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_PRIVID)
-           
-    ) {
-        memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t));
-        memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t));
-        memcpy(stamp, ad_entry(adp, ADEID_PRIVSYN), sizeof(stamp));
-        memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t));
-
-        if (  ( (vol->v_flags & AFPVOL_NODEV) || dev == st->st_dev)
-              && ino == st->st_ino && a_did == did 
-              && !memcmp(vol->v_stamp, stamp, sizeof(stamp))) { 
-           memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
-           return aint;
-        }
+
+    if ((aint = ad_getid(adp, st->st_dev, st->st_ino, did, vol->v_stamp))) {
+       return aint;
     }
 #endif
+
     if (vol->v_cdb != NULL) {
            aint = cnid_add(vol->v_cdb, st, did, upath, len, aint);
            /* Throw errors if cnid_add fails. */
@@ -218,12 +222,13 @@ char   stamp[ADEDLEN_PRIVSYN];
             }
         }
 #if AD_VERSION > AD_VERSION1
-        else if (adp && sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO) {
+        else if (adp ) {
             /* update the ressource fork
              * for a folder adp is always null
              */
-            ad_setid(adp,(vol->v_flags & AFPVOL_NODEV)?0:st->st_dev, st->st_ino, aint, did, vol->v_stamp);
-            ad_flush(adp, ADFLAGS_HF);
+            if (ad_setid(adp, st->st_dev, st->st_ino, aint, did, vol->v_stamp)) {
+                ad_flush(adp, ADFLAGS_HF);
+            }
         }
 #endif    
     }
@@ -277,7 +282,7 @@ int getmetadata(struct vol *vol,
         case FILPBIT_ATTR :
             if ( adp ) {
                 ad_getattr(adp, &ashort);
-            } else if (*upath == '.') {
+            } else if (vol_inv_dots(vol) && *upath == '.') {
                 ashort = htons(ATTRBIT_INVISIBLE);
             } else
                 ashort = 0;
@@ -331,14 +336,8 @@ int getmetadata(struct vol *vol,
             break;
 
         case FILPBIT_FINFO :
-           get_finderinfo(path->m_name, adp, (char *)data);
-            if (!adp) {
-                if (*upath == '.') { /* make it invisible */
-                    ashort = htons(FINDERINFO_INVISIBLE);
-                    memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
-                }
-            }
-            data += 32;
+           get_finderinfo(vol, upath, adp, (char *)data);
+            data += ADEDLEN_FINDERI;
             break;
 
         case FILPBIT_LNAME :
@@ -454,7 +453,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);
 
@@ -465,7 +464,20 @@ int getmetadata(struct vol *vol,
             memcpy( data, &aint, sizeof( aint ));
             data += sizeof( aint );
 
-            aint = htonl(st->st_mode);
+           /* FIXME: ugly hack
+               type == slnk indicates an OSX style symlink, 
+               we have to add S_IFLNK to the mode, otherwise
+               10.3 clients freak out. */
+
+           aint = st->st_mode;
+           if (adp) {
+               memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 );
+                if ( memcmp( fdType, "slnk", 4 ) == 0 ) {
+                   aint |= S_IFLNK;
+               }
+           }
+            aint = htonl(aint);
+
             memcpy( data, &aint, sizeof( aint ));
             data += sizeof( aint );
 
@@ -521,7 +533,7 @@ int getfilparams(struct vol *vol,
            attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
            attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
         } else {
-            ad_init(&ad, vol->v_adouble);
+            ad_init(&ad, vol->v_adouble, vol->v_ad_options);
             adp = &ad;
         }
 
@@ -572,9 +584,9 @@ int getfilparams(struct vol *vol,
 
 /* ----------------------------- */
 int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+AFPObj  *obj;
+char   *ibuf, *rbuf _U_;
+int    ibuflen _U_, *rbuflen;
 {
     struct adouble     ad, *adp;
     struct vol         *vol;
@@ -627,7 +639,7 @@ int         ibuflen, *rbuflen;
     if ((of = of_findname(s_path))) {
         adp = of->of_ad;
     } else {
-        ad_init(&ad, vol->v_adouble);
+        ad_init(&ad, vol->v_adouble, vol->v_ad_options);
         adp = &ad;
     }
     if ( creatf) {
@@ -645,7 +657,7 @@ int         ibuflen, *rbuflen;
         openf = O_RDWR|O_CREAT|O_EXCL;
     }
 
-    if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF,
+    if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
                   openf, 0666, adp) < 0 ) {
         switch ( errno ) {
         case EROFS:
@@ -656,6 +668,9 @@ int         ibuflen, *rbuflen;
             return( AFPERR_EXIST );
         case EACCES :
             return( AFPERR_ACCESS );
+        case EDQUOT:
+        case ENOSPC :
+            return( AFPERR_DFULL );
         default :
             return( AFPERR_PARAM );
         }
@@ -698,9 +713,9 @@ createfile_done:
 }
 
 int afp_setfilparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+AFPObj  *obj;
+char   *ibuf, *rbuf _U_;
+int    ibuflen _U_, *rbuflen;
 {
     struct vol *vol;
     struct dir *dir;
@@ -771,11 +786,10 @@ int setfilparams(struct vol *vol,
                  struct path *path, u_int16_t f_bitmap, char *buf )
 {
     struct adouble     ad, *adp;
-    struct ofork        *of;
     struct extmap      *em;
     int                        bit, isad = 1, err = AFP_OK;
     char                *upath;
-    u_char              achar, *fdType, xyy[4];
+    u_char              achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
     u_int16_t          ashort, bshort;
     u_int32_t          aint;
     u_int32_t          upriv;
@@ -798,12 +812,8 @@ int setfilparams(struct vol *vol,
 #endif /* DEBUG */
 
     upath = path->u_name;
-    if ((of = of_findname(path))) {
-        adp = of->of_ad;
-    } else {
-        ad_init(&ad, vol->v_adouble);
-        adp = &ad;
-    }
+    adp = of_ad(vol, path, &ad);
+    
 
     if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
         return AFPERR_ACCESS;
@@ -942,7 +952,7 @@ int setfilparams(struct vol *vol,
             ad_setdate(adp, AD_DATE_BACKUP, bdate);
             break;
         case FILPBIT_FINFO :
-            if (!memcmp( ad_entry( adp, ADEID_FINDERI ), ufinderi, 8 )
+            if (default_type( ad_entry( adp, ADEID_FINDERI ))
                     && ( 
                      ((em = getextmap( path->m_name )) &&
                       !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) &&
@@ -953,7 +963,6 @@ int setfilparams(struct vol *vol,
             )) {
                 memcpy(finder_buf, ufinderi, 8 );
             }
-
             memcpy(ad_entry( adp, ADEID_FINDERI ), finder_buf, 32 );
             break;
         case FILPBIT_UNIXPR :
@@ -1045,7 +1054,7 @@ 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(vol, vol, src, dst, newname )) ) {
+            if (AFP_OK != ( rc = copyfile(vol, vol, src, dst, newname, NULL )) ) {
                 /* on error copyfile delete dest */
                 return( rc );
             }
@@ -1075,7 +1084,7 @@ 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, vol->v_adouble); 
+            ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
             if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
                ad_close(&ad, ADFLAGS_HF);
                if (!unix_rename( adsrc, vol->ad_path( dst, 0 )) ) 
@@ -1121,7 +1130,21 @@ struct adouble    *adp;
     return( AFP_OK );
 }
 
-int copy_path_name(char *newname, char *ibuf)
+/* ---------------- 
+   convert a Mac long name to an utf8 name,
+*/
+size_t mtoUTF8(const struct vol *vol, const char *src, size_t srclen, char *dest, size_t destlen)
+{
+size_t    outlen;
+
+    if ((size_t)-1 == (outlen = convert_string ( vol->v_maccharset, CH_UTF8_MAC, src, srclen, dest, destlen)) ) {
+       return -1;
+    }
+    return outlen;
+}
+
+/* ---------------- */
+int copy_path_name(const struct vol *vol, char *newname, char *ibuf)
 {
 char        type = *ibuf;
 size_t      plen = 0;
@@ -1135,8 +1158,16 @@ u_int32_t   hint;
     switch (type) {
     case 2:
         if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
-            strncpy( newname, ibuf, plen );
-            newname[ plen ] = '\0';
+            if (afp_version >= 30) {
+                /* convert it to UTF8 
+                */
+                if ((plen = mtoUTF8(vol, ibuf, plen, newname, AFPOBJ_TMPSIZ)) == (size_t)-1)
+                   return -1;
+            }
+            else {
+                strncpy( newname, ibuf, plen );
+                newname[ plen ] = '\0';
+            }
             if (strlen(newname) != plen) {
                 /* there's \0 in newname, e.g. it's a pathname not
                  * only a filename. 
@@ -1171,9 +1202,9 @@ u_int32_t   hint;
 /* -----------------------------------
 */
 int afp_copyfile(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+AFPObj  *obj;
+char   *ibuf, *rbuf _U_;
+int    ibuflen _U_, *rbuflen;
 {
     struct vol *s_vol, *d_vol;
     struct dir *dir;
@@ -1183,6 +1214,9 @@ int               ibuflen, *rbuflen;
     int         err, retvalue = AFP_OK;
     u_int16_t  svid, dvid;
 
+    struct adouble ad, *adp;
+    int denyreadset;
+    
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin afp_copyfile:");
 #endif /* DEBUG */
@@ -1220,11 +1254,20 @@ int             ibuflen, *rbuflen;
      *      and locks need to stay coherent. as a result,
      *      we just balk if the file is opened already. */
 
-    newname = obj->newtmp;
-    strcpy( newname, s_path->m_name );
+    adp = of_ad(s_vol, s_path, &ad);
 
-    if (of_findname(s_path))
+    if (ad_open(s_path->u_name , ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) {
+        return AFPERR_DENYCONF;
+    }
+    denyreadset = (getforkmode(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || 
+                  getforkmode(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
+    ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
+    if (denyreadset) {
         return AFPERR_DENYCONF;
+    }
+
+    newname = obj->newtmp;
+    strcpy( newname, s_path->m_name );
 
     p = ctoupath( s_vol, curdir, newname );
     if (!p) {
@@ -1253,7 +1296,7 @@ int               ibuflen, *rbuflen;
     }
 
     /* one of the handful of places that knows about the path type */
-    if (copy_path_name(newname, ibuf) < 0) {
+    if (copy_path_name(d_vol, newname, ibuf) < 0) {
         return( AFPERR_PARAM );
     }
     /* newname is always only a filename so curdir *is* its
@@ -1262,7 +1305,7 @@ int               ibuflen, *rbuflen;
     if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding()))) {
         return( AFPERR_PARAM );
     }
-    if ( (err = copyfile(s_vol, d_vol, p, upath , newname)) < 0 ) {
+    if ( (err = copyfile(s_vol, d_vol, p, upath , newname, adp)) < 0 ) {
         return err;
     }
     curdir->offcnt++;
@@ -1283,7 +1326,7 @@ int               ibuflen, *rbuflen;
 }
 
 /* ----------------------- */
-static __inline__ int copy_all(const int dfd, const void *buf,
+static int copy_all(const int dfd, const void *buf,
                                size_t buflen)
 {
     ssize_t cc;
@@ -1365,83 +1408,101 @@ 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.
+ * currently if newname is NULL then adp is NULL. 
  */
-int copyfile(s_vol, d_vol, src, dst, newname )
+int copyfile(s_vol, d_vol, src, dst, newname, adp )
 const struct vol *s_vol, *d_vol;
 char   *src, *dst, *newname;
+struct adouble *adp;
 {
     struct adouble     ads, add;
     int                        err = 0;
     int                 ret_err = 0;
     int                 adflags;
     int                 noadouble = vol_noadouble(d_vol);
+    int                 stat_result;
     struct stat         st;
     
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin copyfile:");
 #endif /* DEBUG */
 
-    ad_init(&ads, s_vol->v_adouble); 
-    ad_init(&add, d_vol->v_adouble);
+    if (adp == NULL) {
+        ad_init(&ads, s_vol->v_adouble, s_vol->v_ad_options); 
+        adp = &ads;
+    }
+    ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
     adflags = ADFLAGS_DF;
     if (newname) {
         adflags |= ADFLAGS_HF;
     }
 
-    if (ad_open(src , adflags | ADFLAGS_NOHF, O_RDONLY, 0, &ads) < 0) {
+    if (ad_open(src , adflags | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) {
         ret_err = errno;
         goto done;
     }
 
-    if (ad_hfileno(&ads) == -1) {
+    if (ad_hfileno(adp) == -1) {
         /* no resource fork, don't create one for dst file */
         adflags &= ~ADFLAGS_HF;
     }
 
-    if (ad_open(dst , adflags | noadouble, O_RDWR|O_CREAT|O_EXCL, 0666, &add) < 0) {
+    stat_result = fstat(ad_dfileno(adp), &st); /* saving stat exit code, thus saving us on one more stat later on */
+
+    if (stat_result < 0) {           
+      /* unlikely but if fstat fails, the default file mode will be 0666. */
+      st.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    }
+
+    if (ad_open(dst , adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, &add) < 0) {
         ret_err = errno;
-        ad_close( &ads, adflags );
+        ad_close( adp, adflags );
         if (EEXIST != ret_err) {
             deletefile(d_vol, dst, 0);
             goto done;
         }
         return AFPERR_EXIST;
     }
-    if (ad_hfileno(&ads) == -1 || 0 == (err = copy_fd(ad_hfileno(&add), ad_hfileno(&ads)))){
+    /* XXX if the source and the dest don't use the same resource type it's broken
+    */
+    if (ad_hfileno(adp) == -1 || 0 == (err = copy_fd(ad_hfileno(&add), ad_hfileno(adp)))){
         /* copy the data fork */
-       err = copy_fd(ad_dfileno(&add), ad_dfileno(&ads));
+       err = copy_fd(ad_dfileno(&add), ad_dfileno(adp));
     }
 
     /* Now, reopen destination file */
     if (err < 0) {
        ret_err = errno;
     }
-    ad_close( &ads, adflags );
+    ad_close( adp, adflags );
 
     if (ad_close( &add, adflags ) <0) {
+        if (!ret_err) {
+            ret_err = errno;
+        }
         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) {
+
+    if (!ret_err && newname && (adflags & ADFLAGS_HF)) {
+        /* set the new name in the resource fork */
+       ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
+       if (ad_open(dst , ADFLAGS_HF | noadouble, O_RDWR, 0666, &add) < 0) {
            ret_err = errno;
        }
+       else {
+            ad_setname(&add, newname);
+            ad_flush( &add, ADFLAGS_HF );
+            if (ad_close( &add, ADFLAGS_HF ) <0) {
+                ret_err = errno;
+            }
+        }
     }
 
-    if (!ret_err && newname) {
-        ad_setname(&add, newname);
-    }
-
-    ad_flush( &add, adflags );
-    if (ad_close( &add, adflags ) <0) {
-       ret_err = errno;
-    }
     if (ret_err) {
         deletefile(d_vol, dst, 0);
     }
-    else if (!stat(src, &st)) {
+    else if (stat_result == 0) {
         /* set dest modification date to src date */
         struct utimbuf ut;
 
@@ -1500,8 +1561,8 @@ int         checkAttrib;
 
     /* try to open both forks at once */
     adflags = ADFLAGS_DF|ADFLAGS_HF;
+    ad_init(&ad, vol->v_adouble, vol->v_ad_options);  /* OK */
     while(1) {
-        ad_init(&ad, vol->v_adouble);  /* OK */
         if ( ad_open( file, adflags, O_RDONLY, 0, &ad ) < 0 ) {
             switch (errno) {
             case ENOENT:
@@ -1539,7 +1600,7 @@ int         checkAttrib;
         }
         else if (!adp) {
             /* was EACCESS error try to get only metadata */
-            ad_init(&ad, vol->v_adouble);  /* OK */
+            ad_init(&ad, vol->v_adouble, vol->v_ad_options);  /* OK */
             if ( ad_metadata( file , 0, &ad) == 0 ) {
                 ad_getattr(&ad, &bshort);
                 ad_close( &ad, ADFLAGS_HF );
@@ -1591,9 +1652,9 @@ int         checkAttrib;
 /* ------------------------------------ */
 /* return a file id */
 int afp_createid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
+AFPObj  *obj _U_;
 char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int    ibuflen _U_, *rbuflen;
 {
     struct stat         *st;
     struct vol         *vol;
@@ -1701,24 +1762,20 @@ reenumerate_id(const struct vol *vol, char *name, cnid_t did)
 
 #if AD_VERSION > AD_VERSION1
         if (aint != CNID_INVALID && !S_ISDIR(path.st.st_mode)) {
-            struct ofork    *of;
             struct adouble  ad, *adp;
 
             path.st_errno = 0;
             path.st_valid = 1;
             path.u_name = de->d_name;
             
-            if (!(of = of_findname(&path))) {
-                ad_init(&ad, vol->v_adouble);
-                adp = &ad;
-            } else
-                adp = of->of_ad;
+            adp = of_ad(vol, &path, &ad);
             
             if ( ad_open( de->d_name, ADFLAGS_HF, O_RDWR, 0, adp ) < 0 ) {
                 continue;
             }
-            ad_setid(adp,(vol->v_flags & AFPVOL_NODEV)?0:path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp);
-            ad_flush(adp, ADFLAGS_HF);
+            if (ad_setid(adp, path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp)) {
+               ad_flush(adp, ADFLAGS_HF);
+            }
             ad_close(adp, ADFLAGS_HF);
         }
 #endif /* AD_VERSION > AD_VERSION1 */
@@ -1733,9 +1790,9 @@ reenumerate_id(const struct vol *vol, char *name, cnid_t did)
 /* ------------------------------
    resolve a file id */
 int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
+AFPObj      *obj _U_;
 char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int            ibuflen _U_, *rbuflen;
 {
     struct vol         *vol;
     struct dir         *dir;
@@ -1769,7 +1826,11 @@ int              ibuflen, *rbuflen;
     memcpy(&id, ibuf, sizeof( id ));
     ibuf += sizeof(id);
     cnid = id;
-
+    
+    if (!id) {
+        /* some MacOS versions after a catsearch do a *lot* of afp_resolveid with 0 */
+        return AFPERR_NOID;
+    }
 retry:
     if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
         return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
@@ -1841,9 +1902,9 @@ retry:
 
 /* ------------------------------ */
 int afp_deleteid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+AFPObj  *obj _U_;
+char   *ibuf, *rbuf _U_;
+int    ibuflen _U_, *rbuflen;
 {
     struct stat         st;
     struct vol         *vol;
@@ -1977,9 +2038,9 @@ static struct adouble *find_adouble(struct path *path, struct ofork **of, struct
 #define APPLETEMP ".AppleTempXXXXXX"
 
 int afp_exchangefiles(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+AFPObj  *obj;
+char   *ibuf, *rbuf _U_ ;
+int    ibuflen _U_, *rbuflen;
 {
     struct stat         srcst, destst;
     struct vol         *vol;
@@ -2052,7 +2113,7 @@ int               ibuflen, *rbuflen;
         return AFPERR_PARAM ;
     }
     
-    ad_init(&ads, vol->v_adouble);
+    ad_init(&ads, vol->v_adouble, vol->v_ad_options);
     if (!(adsp = find_adouble( path, &s_of, &ads))) {
         return afp_errno;
     }
@@ -2085,7 +2146,7 @@ int               ibuflen, *rbuflen;
         goto err_exchangefile;
     }
 
-    ad_init(&add, vol->v_adouble);
+    ad_init(&add, vol->v_adouble, vol->v_ad_options);
     if (!(addp = find_adouble( path, &d_of, &add))) {
         err = afp_errno;
         goto err_exchangefile;
@@ -2116,7 +2177,7 @@ int               ibuflen, *rbuflen;
     }
     
     if (crossdev) {
-        /* we need to close fork for copy, both s_of and d_of are null */
+        /* FIXME we need to close fork for copy, both s_of and d_of are null */
        ad_close(adsp, ADFLAGS_HF);
        ad_close(addp, ADFLAGS_HF);
     }
@@ -2163,10 +2224,15 @@ int             ibuflen, *rbuflen;
     }
     
     /* here we need to reopen if crossdev */
-    if (sid)
-        ad_setid(addp,(vol->v_flags & AFPVOL_NODEV)?0:destst.st_dev, destst.st_ino,  sid, sdir->d_did, vol->v_stamp);
-    if (did)
-        ad_setid(adsp,(vol->v_flags & AFPVOL_NODEV)?0:srcst.st_dev, srcst.st_ino,  did, curdir->d_did, vol->v_stamp);
+    if (sid && ad_setid(addp, destst.st_dev, destst.st_ino,  sid, sdir->d_did, vol->v_stamp)) 
+    {
+       ad_flush( addp, ADFLAGS_HF );
+    }
+        
+    if (did && ad_setid(adsp, srcst.st_dev, srcst.st_ino,  did, curdir->d_did, vol->v_stamp)) 
+    {
+       ad_flush( adsp, ADFLAGS_HF );
+    }
 
     /* change perms, src gets dest perm and vice versa */
 
@@ -2231,11 +2297,9 @@ err_src_to_tmp:
 
 err_exchangefile:
     if ( !s_of && adsp && ad_hfileno(adsp) != -1 ) {
-       ad_flush( adsp, ADFLAGS_HF );
        ad_close(adsp, ADFLAGS_HF);
     }
     if ( !d_of && addp && ad_hfileno(addp) != -1 ) {
-       ad_flush( addp, ADFLAGS_HF );
        ad_close(addp, ADFLAGS_HF);
     }