]> arthur.barton.de Git - netatalk.git/commitdiff
add a SFM compatible format for adouble after_sfm
authordidg <didg>
Fri, 29 Sep 2006 09:39:16 +0000 (09:39 +0000)
committerdidg <didg>
Fri, 29 Sep 2006 09:39:16 +0000 (09:39 +0000)
18 files changed:
bin/megatron/nad.c
etc/afpd/desktop.c
etc/afpd/directory.c
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/fork.c
etc/afpd/ofork.c
etc/afpd/vfs_adouble.c
etc/afpd/volume.c
include/atalk/adouble.h
libatalk/adouble/ad_attr.c
libatalk/adouble/ad_date.c
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_lock.c
libatalk/adouble/ad_open.c
libatalk/adouble/ad_read.c
libatalk/adouble/ad_size.c
libatalk/adouble/ad_write.c

index 2b1c14c8deed06c5f6f8d33c801d93b33c978bd2..f9aab5d5335c9bc9134c11fd5f13d4e8c0959d9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: nad.c,v 1.14 2006-09-19 01:35:45 didg Exp $
+ * $Id: nad.c,v 1.15 2006-09-29 09:39:16 didg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -451,7 +451,7 @@ int nad_open( path, openflags, fh, options )
        initvol(path);
        strcpy( nad.adpath[0], path );
        strcpy( nad.adpath[1], 
-               nad.ad.ad_path( nad.adpath[0], ADFLAGS_DF|ADFLAGS_HF ));
+               nad.ad.ad_ops->ad_path( nad.adpath[0], ADFLAGS_HF ));
        for ( fork = 0 ; fork < NUMFORKS ; fork++ ) {
            if ( stat( nad.adpath[ fork ], &st ) < 0 ) {
                if ( errno == ENOENT ) {
@@ -479,7 +479,7 @@ int nad_open( path, openflags, fh, options )
        strcpy( nad.macname, fh->name );
        strcpy( nad.adpath[0], mtoupath( nad.macname ));
        strcpy( nad.adpath[1], 
-               nad.ad.ad_path( nad.adpath[0], ADFLAGS_DF|ADFLAGS_HF ));
+               nad.ad.ad_ops->ad_path( nad.adpath[0], ADFLAGS_HF ));
 #if DEBUG
     fprintf(stderr, "%s\n", nad.macname);
     fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
@@ -691,7 +691,7 @@ int nad_header_write( fh )
 #endif /* HEXOUTPUT */
 
     nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
-    ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF );
+    ad_flush( &nad.ad );
 
     return( 0 );
 }
@@ -763,7 +763,7 @@ int                 status;
 {
     int                        rv;
     if ( status == KEEP ) {
-       if (( rv = ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
+       if (( rv = ad_flush( &nad.ad )) < 0 ) {
            fprintf( stderr, "nad_close rv for flush %d\n", rv );
            return( rv );
        }
index dcefcc849b06dade8dddbfa5b763115df2a246be..927be9d4d66ef3d896d7761d604e2d5e33972315 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: desktop.c,v 1.36 2006-09-19 01:35:45 didg Exp $
+ * $Id: desktop.c,v 1.37 2006-09-29 09:39:16 didg Exp $
  *
  * See COPYRIGHT.
  *
@@ -748,7 +748,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
     }
 
     if (ad_getentryoff(adp, ADEID_COMMENT)) {
-        if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
+        if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
             if ( *path->m_name == '\0' ) {
                 name = curdir->d_m_name;
             } else {
@@ -758,7 +758,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
         }
         ad_setentrylen( adp, ADEID_COMMENT, clen );
         memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
-        ad_flush_metadata( adp );
+        ad_flush( adp );
     }
     ad_close_metadata( adp);
     return( AFP_OK );
@@ -912,7 +912,7 @@ static int ad_rmvcomment(struct vol *vol, struct path *path)
 
     if (ad_getentryoff(adp, ADEID_COMMENT)) {
         ad_setentrylen( adp, ADEID_COMMENT, 0 );
-        ad_flush_metadata( adp );
+        ad_flush( adp );
     }
     ad_close_metadata( adp);
     return( AFP_OK );
index 224f397973e7500aacaf5c60049d4f7a1d9e262c..b9c687746ab9616c5a85d376c2b1b0213e20241e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.83 2006-09-19 23:00:49 didg Exp $
+ * $Id: directory.c,v 1.84 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -2253,7 +2253,7 @@ setdirparam_done:
                 ad_setid(&ad, st->st_dev, st->st_ino,  dir->d_did, dir->d_parent->d_did, vol->v_stamp);
             }
         }
-        ad_flush_metadata( &ad);
+        ad_flush( &ad);
         ad_close_metadata( &ad);
     }
 
@@ -2344,7 +2344,7 @@ int       ibuflen _U_, *rbuflen;
     ad_setname(&ad, s_path->m_name);
     ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
 
-    ad_flush_metadata( &ad);
+    ad_flush( &ad);
     ad_close_metadata( &ad);
 
 createdir_done:
@@ -2408,7 +2408,7 @@ struct dir        *dir, *newparent;
 
     if (!ad_open_metadata( dst, ADFLAGS_DIR, 0, &ad)) {
         ad_setname(&ad, newname);
-        ad_flush_metadata( &ad);
+        ad_flush( &ad);
         ad_close_metadata( &ad);
     }
 
index 523cda413805db91ce38ae5af138c4208aedc3b9..e091ba0fdadd258a5a0d08a2c698184b354ccc73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.102 2006-09-19 23:00:49 didg Exp $
+ * $Id: file.c,v 1.103 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -227,7 +227,7 @@ u_int32_t aint = 0;
              * for a folder adp is always null
              */
             if (ad_setid(adp, st->st_dev, st->st_ino, aint, did, vol->v_stamp)) {
-                ad_flush(adp, ADFLAGS_HF);
+                ad_flush(adp);
             }
         }
 #endif    
@@ -239,7 +239,7 @@ u_int32_t aint = 0;
 int getmetadata(struct vol *vol,
                  u_int16_t bitmap,
                  struct path *path, struct dir *dir, 
-                 char *buf, int *buflen, struct adouble *adp, int attrbits )
+                 char *buf, int *buflen, struct adouble *adp)
 {
     char               *data, *l_nameoff = NULL, *upath;
     char                *utf_nameoff = NULL;
@@ -296,12 +296,10 @@ int getmetadata(struct vol *vol,
             if ((ma.ma_user & AR_UWRITE)) {
                accessmode( upath, &ma, dir , st);
                if (!(ma.ma_user & AR_UWRITE)) {
-                       attrbits |= ATTRBIT_NOWRITE;
+                       ashort |= htons(ATTRBIT_NOWRITE);
                 }
             }
 #endif
-            if (attrbits)
-                ashort = htons(ntohs(ashort) | attrbits);
             memcpy(data, &ashort, sizeof( ashort ));
             data += sizeof( ashort );
             break;
@@ -518,7 +516,6 @@ int getfilparams(struct vol *vol,
     struct adouble     ad, *adp;
     struct ofork        *of;
     char                   *upath;
-    u_int16_t          attrbits = 0;
     int                 opened = 0;
     int rc;    
 
@@ -528,18 +525,18 @@ int getfilparams(struct vol *vol,
 
     opened = PARAM_NEED_ADP(bitmap);
     adp = NULL;
+
     if (opened) {
+        int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
         upath = path->u_name;
         if ((of = of_findname(path))) {
             adp = of->of_ad;
-           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, vol->v_ad_options);
             adp = &ad;
         }
 
-        if ( ad_metadata( upath, 0, adp) < 0 ) {
+        if ( ad_metadata( upath, flags, adp) < 0 ) {
             switch (errno) {
             case EACCES:
                 LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
@@ -554,26 +551,8 @@ int getfilparams(struct vol *vol,
                 break;
             }
         }
-        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:
-              - bitmap is requested.
-              - we don't already have the answer!
-           */
-           if ((bitmap & (1 << FILPBIT_ATTR))) {
-                if (!(attrbits & ATTRBIT_ROPEN)) {
-                    attrbits |= ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_OPEN_RD) > 0? ATTRBIT_ROPEN : 0;
-                    attrbits |= ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_OPEN_WR) > 0? ATTRBIT_ROPEN : 0;
-                }
-                if (!(attrbits & ATTRBIT_DOPEN)) {
-                    attrbits |= ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_OPEN_RD) > 0? ATTRBIT_DOPEN : 0;
-                    attrbits |= ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_OPEN_WR) > 0? ATTRBIT_DOPEN : 0;
-                }
-           }
-       }
     }
-    rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp, attrbits);
+    rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
     if ( adp ) {
         ad_close_metadata( adp);
     }
@@ -677,7 +656,7 @@ int ibuflen _U_, *rbuflen;
             return( AFPERR_PARAM );
         }
     }
-    if ( ad_hfileno( adp ) == -1 ) {
+    if ( ad_reso_fileno( adp ) == -1 ) { /* Hard META / HF */
          /* on noadouble volumes, just creating the data fork is ok */
          if (vol_noadouble(vol)) {
              ad_close( adp, ADFLAGS_DF );
@@ -693,7 +672,7 @@ int ibuflen _U_, *rbuflen;
 
     path = s_path->m_name;
     ad_setname(adp, path);
-    ad_flush( adp, ADFLAGS_DF|ADFLAGS_HF );
+    ad_flush( adp);
     ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
 
 createfile_done:
@@ -998,7 +977,7 @@ setfilparam_done:
     }
 
     if (isad) {
-        ad_flush_metadata( adp);
+        ad_flush( adp);
         ad_close_metadata( adp);
 
     }
@@ -1050,7 +1029,7 @@ struct adouble    *adp;
             * get two files, it's fixable for our process (eg reopen the new file, get the
             * locks, and so on. But it doesn't solve the case with a second process
             */
-           if (adp->ad_df.adf_refcount || adp->ad_hf.adf_refcount) {
+           if (adp->ad_open_forks) {
                /* FIXME  warning in syslog so admin'd know there's a conflict ?*/
                return AFPERR_OLOCK; /* little lie */
            }
@@ -1092,7 +1071,7 @@ struct adouble    *adp;
      */
     if (!ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) {
         ad_setname(adp, newname);
-        ad_flush( adp, ADFLAGS_HF );
+        ad_flush( adp );
         ad_close( adp, ADFLAGS_HF );
     }
 #ifdef DEBUG
@@ -1326,13 +1305,31 @@ static __inline__ int copy_all(const int dfd, const void *buf,
     return 0;
 }
 
-/* -------------------------- */
-static int copy_fd(int dfd, int sfd)
+/* -------------------------- 
+ * copy only the fork data stream
+*/
+static int copy_fork(int eid, struct adouble *add, struct adouble *ads)
 {
     ssize_t cc;
     int     err = 0;
     char    filebuf[8192];
+    int     sfd, dfd;
     
+    if (eid == ADEID_DFORK) {
+        sfd = ad_data_fileno(ads);
+        dfd = ad_data_fileno(add);
+    }
+    else {
+        sfd = ad_reso_fileno(ads);
+        dfd = ad_reso_fileno(add);
+    }        
+
+    if ((off_t)-1 == lseek(sfd, ad_getentryoff(ads, eid), SEEK_SET))
+       return -1;
+
+    if ((off_t)-1 == lseek(dfd, ad_getentryoff(add, eid), SEEK_SET))
+       return -1;
+       
 #if 0 /* ifdef SENDFILE_FLAVOR_LINUX */
     /* doesn't work With 2.6 FIXME, only check for EBADFD ? */
     off_t   offset = 0;
@@ -1378,7 +1375,7 @@ static int copy_fd(int dfd, int sfd)
 }
 
 /* ----------------------------------
- * if newname is NULL (from directory.c) we don't want to copy ressource fork.
+ * if newname is NULL (from directory.c) we don't want to copy the resource fork.
  * because we are doing it elsewhere.
  * currently if newname is NULL then adp is NULL. 
  */
@@ -1414,12 +1411,12 @@ struct adouble *adp;
         goto done;
     }
 
-    if (ad_hfileno(adp) == -1) {
+    if (ad_meta_fileno(adp) == -1 && ad_reso_fileno(adp) == -1) { /* META / HF */
         /* no resource fork, don't create one for dst file */
         adflags &= ~ADFLAGS_HF;
     }
 
-    stat_result = fstat(ad_dfileno(adp), &st); /* saving stat exit code, thus saving us on one more stat later on */
+    stat_result = fstat(ad_data_fileno(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. */
@@ -1437,39 +1434,26 @@ struct adouble *adp;
     }
     /* 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)))){
+    if (ad_reso_fileno(adp) == -1 || 0 == (err = copy_fork(ADEID_RFORK, &add, adp))){
         /* copy the data fork */
-       err = copy_fd(ad_dfileno(&add), ad_dfileno(adp));
+       err = copy_fork(ADEID_DFORK, &add, adp);
     }
 
-    /* Now, reopen destination file */
     if (err < 0) {
        ret_err = errno;
     }
-    ad_close( adp, adflags );
-
-    if (ad_close( &add, adflags ) <0) {
-        if (!ret_err) {
-            ret_err = errno;
-        }
-        deletefile(d_vol, dst, 0);
-        goto done;
-    } 
 
     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_metadata(dst , noadouble, 0, &add) < 0) {
-           ret_err = errno;
-       }
-       else {
-            ad_setname(&add, newname);
-            ad_flush_metadata( &add);
-            if (ad_close_metadata( &add)) {
-                ret_err = errno;
-            }
-        }
+        ad_copy_header(&add, adp);
+        ad_setname(&add, newname);
+        ad_flush( &add );
     }
+    ad_close( adp, adflags );
+
+    if (ad_close( &add, adflags ) <0) {
+       ret_err = errno;
+    } 
 
     if (ret_err) {
         deletefile(d_vol, dst, 0);
@@ -1518,6 +1502,24 @@ done:
    ad_open always try to open file RDWR first and ad_lock takes care of
    WRITE lock on read only file.
 */
+
+static int check_attrib(struct adouble *adp)
+{
+u_int16_t   bshort = 0;
+
+       ad_getattr(adp, &bshort);
+    /*
+     * Does kFPDeleteInhibitBit (bit 8) set?
+     */
+       if ((bshort & htons(ATTRBIT_NODELETE))) {
+               return AFPERR_OLOCK;
+       }
+    if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
+       return AFPERR_BUSY;
+       }
+       return 0;
+}
+
 int deletefile( vol, file, checkAttrib )
 const struct vol      *vol;
 char           *file;
@@ -1533,8 +1535,19 @@ 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 */
+    if (checkAttrib) {
+        /* was EACCESS error try to get only metadata */
+        ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+        if ( ad_metadata( file , ADFLAGS_OPENFORKS, &ad) == 0 ) {
+            ad_close( &ad, adflags );
+            if ((err = check_attrib(&ad))) {
+               return err;
+            }
+        }
+    }
     while(1) {
+       ad_init(&ad, vol->v_adouble, vol->v_ad_options);  /* OK */
         if ( ad_open( file, adflags, O_RDONLY, 0, &ad ) < 0 ) {
             switch (errno) {
             case ENOENT:
@@ -1556,21 +1569,7 @@ int         checkAttrib;
         }
         break; /* from the while */
     }
-    /*
-     * Does kFPDeleteInhibitBit (bit 8) set?
-     */
-    if (checkAttrib) {
-        u_int16_t   bshort;
-        
-        if ( ad_metadata( file , 0, &ad) == 0 ) {
-            ad_getattr(&ad, &bshort);
-            ad_close_metadata( &ad);
-            if ((bshort & htons(ATTRBIT_NODELETE))) {
-                return  AFPERR_OLOCK;
-            }
-        }
-    }
-    
+
     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
@@ -1727,7 +1726,7 @@ static int reenumerate_loop(struct dirent *de, char *mname _U_, void *data)
             return 0;
         }
         if (ad_setid(adp, path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp)) {
-            ad_flush_metadata(adp);
+            ad_flush(adp);
         }
         ad_close_metadata(adp);
     }
@@ -2009,7 +2008,8 @@ static struct adouble *find_adouble(struct path *path, struct ofork **of, struct
     }
     else {
         ret = ad_open( path->u_name, ADFLAGS_HF, O_RDONLY, 0, adp);
-        if ( !ret && ad_hfileno(adp) != -1 && !(adp->ad_hf.adf_flags & ( O_RDWR | O_WRONLY))) {
+        /* META and HF */
+        if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) {
             /* from AFP spec.
              * The user must have the Read & Write privilege for both files in order to use this command.
              */
@@ -2212,12 +2212,12 @@ int     ibuflen _U_, *rbuflen;
     /* here we need to reopen if crossdev */
     if (sid && ad_setid(addp, destst.st_dev, destst.st_ino,  sid, sdir->d_did, vol->v_stamp)) 
     {
-       ad_flush( addp, ADFLAGS_HF );
+       ad_flush( addp );
     }
         
     if (did && ad_setid(adsp, srcst.st_dev, srcst.st_ino,  did, curdir->d_did, vol->v_stamp)) 
     {
-       ad_flush( adsp, ADFLAGS_HF );
+       ad_flush( adsp );
     }
 
     /* change perms, src gets dest perm and vice versa */
@@ -2282,10 +2282,10 @@ err_src_to_tmp:
     of_rename(vol, s_of, curdir, temp, sdir, spath);
 
 err_exchangefile:
-    if ( !s_of && adsp && ad_hfileno(adsp) != -1 ) {
+    if ( !s_of && adsp && ad_meta_fileno(adsp) != -1 ) { /* META */
        ad_close(adsp, ADFLAGS_HF);
     }
-    if ( !d_of && addp && ad_hfileno(addp) != -1 ) {
+    if ( !d_of && addp && ad_meta_fileno(addp) != -1 ) {/* META */
        ad_close(addp, ADFLAGS_HF);
     }
 
index dba239505ee116462f02586c0a1901348d3daf15..06fe64bea53ea3bd02f779199f04bacc361df7e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.19 2006-09-19 23:00:50 didg Exp $
+ * $Id: file.h,v 1.20 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -58,8 +58,13 @@ extern const u_char  ufinderi[];
 #define ATTRBIT_INVISIBLE (1<<0)  /* invisible (d) */
 #define ATTRBIT_MULTIUSER (1<<1)  /* multiuser */
 #define ATTRBIT_SYSTEM    (1<<2)  /* system (d) */
+
+#if 0
+/* define in adouble.h */
 #define ATTRBIT_DOPEN     (1<<3)  /* data fork already open */
 #define ATTRBIT_ROPEN     (1<<4)  /* resource fork already open */
+#endif
+
 #define ATTRBIT_SHARED    (1<<4)  /* shared area (d) */
 #define ATTRBIT_NOWRITE   (1<<5)  /* write inhibit(v2)/read-only(v1) bit */
 #define ATTRBIT_BACKUP    (1<<6)  /* backup needed (d) */
index 1df39a0fd0762b149d76fd9f8b6a9caf218187fb..09b8ed5212f3e6b8dee52ec61c2cb18eee36be25 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.55 2005-09-28 09:46:37 didg Exp $
+ * $Id: fork.c,v 1.56 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -48,14 +48,13 @@ struct ofork                *writtenfork;
 extern int getmetadata(struct vol *vol,
                  u_int16_t bitmap,
                  struct path *path, struct dir *dir, char *buf, 
-                 int *buflen, struct adouble *adp, int attrbits );
+                 int *buflen, struct adouble *adp);
 
-static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
+static int getforkparams(ofork, bitmap, buf, buflen )
 struct ofork   *ofork;
 u_int16_t              bitmap;
 char           *buf;
 int                    *buflen;
-const u_int16_t     attrbits;
 {
     struct path         path;
     struct stat                *st;
@@ -74,7 +73,7 @@ const u_int16_t     attrbits;
         return( AFPERR_BITMAP );
     }
 
-    if ( ad_hfileno( ofork->of_ad ) == -1 ) {
+    if ( ad_reso_fileno( ofork->of_ad ) == -1 ) { /* META ? */
         adp = NULL;
     } else {
         adp = ofork->of_ad;
@@ -91,18 +90,18 @@ const u_int16_t     attrbits;
     if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
                     (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | 
                     (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
-        if ( ad_dfileno( ofork->of_ad ) == -1 ) {
+        if ( ad_data_fileno( ofork->of_ad ) == -1 ) {
             if (movecwd(vol, dir) < 0)
                 return( AFPERR_NOOBJ );
             if ( stat( path.u_name, st ) < 0 )
                 return( AFPERR_NOOBJ );
         } else {
-            if ( fstat( ad_dfileno( ofork->of_ad ), st ) < 0 ) {
+            if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) {
                 return( AFPERR_BITMAP );
             }
         }
     }
-    return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp, attrbits );    
+    return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
 }
 
 /* ---------------------------- */
@@ -269,7 +268,7 @@ int ibuflen _U_, *rbuflen;
     struct adouble      *adsame = NULL;
     int                        buflen, ret, adflags, eid;
     u_int32_t           did;
-    u_int16_t          vid, bitmap, access, ofrefnum, attrbits = 0;
+    u_int16_t          vid, bitmap, access, ofrefnum;
     char               fork, *path, *upath;
     struct stat         *st;
     u_int16_t           bshort;
@@ -346,9 +345,6 @@ int ibuflen _U_, *rbuflen;
        FIXME: add the fork we are opening? 
     */
     if ((opened = of_findname(s_path))) {
-        attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
-        attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
-                   
         adsame = opened->of_ad;
     }
 
@@ -462,12 +458,12 @@ int       ibuflen _U_, *rbuflen;
 
     if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
         if (ad_setname(ofork->of_ad, path)) {
-            ad_flush( ofork->of_ad, adflags );
+            ad_flush( ofork->of_ad );
         }
     }
 
     if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
-                              &buflen, attrbits )) != AFP_OK ) {
+                              &buflen )) != AFP_OK ) {
         ad_close( ofork->of_ad, adflags );
         goto openfork_err;
     }
@@ -480,7 +476,7 @@ int ibuflen _U_, *rbuflen;
     /* check  WriteInhibit bit if we have a ressource fork
      * the test is done here, after some Mac trafic capture 
      */
-    if (ad_hfileno(ofork->of_ad) != -1) {
+    if (ad_meta_fileno(ofork->of_ad) != -1) {   /* META */
         ad_getattr(ofork->of_ad, &bshort);
         if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
             ad_close( ofork->of_ad, adflags );
@@ -496,7 +492,7 @@ int ibuflen _U_, *rbuflen;
      */
 
     /* don't try to lock non-existent rforks. */
-    if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
+    if ((eid == ADEID_DFORK) || (ad_meta_fileno(ofork->of_ad) != -1)) { /* META */
 
         ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
         /* can we access the fork? */
@@ -629,7 +625,7 @@ int ibuflen, *rbuflen;
         if (err < 0)
             goto afp_setfork_err;
 
-        if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
+        if (ad_flush( ofork->of_ad ) < 0) {
             LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) );
             return AFPERR_PARAM;
         }
@@ -717,7 +713,7 @@ int     is64;
         length = BYTELOCK_MAX;
      else if (!length || is_neg(is64, length)) {
        return AFPERR_PARAM;
-     } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_hfileno(ofork->of_ad))) {
+     } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
         return AFPERR_LOCK;
     }
 
@@ -783,7 +779,7 @@ struct ofork        *of;
 {
     struct extmap      *em;
 
-    if ( ad_hfileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) {
+    if ( ad_meta_fileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) { /* META */
         /* no resource fork or no finderinfo, use our files extension mapping */
         if (!( em = getextmap( of_name(of) )) || memcmp( "TEXT", em->em_type, sizeof( em->em_type ))) {
             return 0;
@@ -1110,14 +1106,14 @@ struct ofork    *ofork;
 
     int err = 0, doflush = 0;
 
-    if ( ad_dfileno( ofork->of_ad ) != -1 &&
-            fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
+    if ( ad_data_fileno( ofork->of_ad ) != -1 &&
+            fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
         LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
-            of_name(ofork), ad_dfileno(ofork->of_ad), strerror(errno) );
+            of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) );
         err = -1;
     }
 
-    if ( ad_hfileno( ofork->of_ad ) != -1 && 
+    if ( ad_reso_fileno( ofork->of_ad ) != -1 &&  /* HF */
            (ofork->of_flags & AFPFORK_RSRC)) {
 
         /* read in the rfork length */
@@ -1131,15 +1127,15 @@ struct ofork    *ofork;
         }
 
         /* flush the header */
-        if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)
+        if (doflush && ad_flush(ofork->of_ad) < 0)
                 err = -1;
 
-        if (fsync( ad_hfileno( ofork->of_ad )) < 0)
+        if (fsync( ad_reso_fileno( ofork->of_ad )) < 0)
             err = -1;
 
         if (err < 0)
             LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s",
-                of_name(ofork), ad_hfileno(ofork->of_ad), strerror(errno) );
+                of_name(ofork), ad_reso_fileno(ofork->of_ad), strerror(errno) );
     }
 
     return( err );
@@ -1375,7 +1371,7 @@ int                 is64;
     }
 
     ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount,  ofork->of_refnum);
-    if ( ad_hfileno( ofork->of_ad ) != -1 )
+    if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */
         ofork->of_flags |= AFPFORK_DIRTY;
 
     *rbuflen = set_off_t (offset, rbuf, is64);
@@ -1421,7 +1417,6 @@ int       ibuflen _U_, *rbuflen;
     struct ofork       *ofork;
     int                        buflen, ret;
     u_int16_t          ofrefnum, bitmap;
-    u_int16_t          attrbits = 0;
 
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
@@ -1435,10 +1430,8 @@ int      ibuflen _U_, *rbuflen;
         LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum );
         return( AFPERR_PARAM );
     }
-    attrbits = ((ofork->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
-    attrbits |= ((ofork->of_ad->ad_hf.adf_refcount > ofork->of_ad->ad_df.adf_refcount) ? ATTRBIT_ROPEN : 0);
 
-    if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+    if ( ad_meta_fileno( ofork->of_ad ) != -1 ) { /* META */
         if ( ad_refresh( ofork->of_ad ) < 0 ) {
             LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) );
             return( AFPERR_PARAM );
@@ -1446,7 +1439,7 @@ int       ibuflen _U_, *rbuflen;
     }
 
     if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
-                               rbuf + sizeof( u_short ), &buflen, attrbits ))) {
+                               rbuf + sizeof( u_short ), &buflen ))) {
         return( ret );
     }
 
index e4ec59b5f2d5943d4843ab5b5408f43338c3532f..abf7b474db04014d0a57e307c8dd1c19abddc6f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ofork.c,v 1.24 2005-09-28 09:46:37 didg Exp $
+ * $Id: ofork.c,v 1.25 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1996 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -387,10 +387,10 @@ int of_closefork(struct ofork *ofork)
     int                 ret;
 
     adflags = 0;
-    if ((ofork->of_flags & AFPFORK_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) {
+    if ((ofork->of_flags & AFPFORK_DATA) && (ad_data_fileno( ofork->of_ad ) != -1)) {
             adflags |= ADFLAGS_DF;
     }
-    if ( (ofork->of_flags & AFPFORK_OPEN) && ad_hfileno( ofork->of_ad ) != -1 ) {
+    if ( (ofork->of_flags & AFPFORK_OPEN) && ad_reso_fileno( ofork->of_ad ) != -1 ) {
         adflags |= ADFLAGS_HF;
         /*
          * Only set the rfork's length if we're closing the rfork.
@@ -402,7 +402,7 @@ int of_closefork(struct ofork *ofork)
                doflush++;
             }
             if ( doflush ) {
-                 ad_flush( ofork->of_ad, adflags );
+                 ad_flush( ofork->of_ad );
             }
         }
     }
index 30d84c69ef4972c7c6862d067f897154ac837225..1fae02b09f63bfafe7e84b0ed00ea0f14a2c59ca 100644 (file)
@@ -742,6 +742,24 @@ struct vfs_ops netatalk_adouble_ads = {
     /* rf_renamefile:    */ RF_renamefile_ads,
 };
 
+/* =======================================
+   samba sfm format
+   ad_path shouldn't be set here
+ */
+struct vfs_ops netatalk_adouble_sfm = {
+    /* ad_path:          */ ad_path_sfm,
+    /* validupath:       */ validupath_adouble,
+    /* rf_chown:         */ RF_chown_ads,
+    /* rf_renamedir:     */ RF_renamedir_adouble,
+    /* rf_deletecurdir:  */ RF_deletecurdir_ads,
+    /* rf_setfilmode:    */ RF_setfilmode_ads,
+    /* rf_setdirmode:    */ RF_setdirmode_ads,
+    /* rf_setdirunixmode:*/ RF_setdirunixmode_ads,
+    /* rf_setdirowner:   */ RF_setdirowner_ads,
+    /* rf_deletefile:    */ RF_deletefile_ads,
+    /* rf_renamefile:    */ RF_renamefile_ads,
+};
+
 /* ---------------- */
 void initvol_vfs(struct vol *vol)
 {
@@ -751,6 +769,9 @@ void initvol_vfs(struct vol *vol)
     else if (vol->v_adouble == AD_VERSION1_ADS) {
         vol->vfs = &netatalk_adouble_ads;
     }
+    else if (vol->v_adouble == AD_VERSION1_SFM) {
+        vol->vfs = &netatalk_adouble_sfm;
+    }
     else {
         vol->vfs = &netatalk_adouble;
     }
index 56a6d6fd4ad63dceb64d6381246bbda28632db1e..9c5272458c9b108fee8834aeaa3c4fe2c974978a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.67 2006-09-19 23:00:50 didg Exp $
+ * $Id: volume.c,v 1.68 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -436,6 +436,8 @@ static void volset(struct vol_option *options, struct vol_option *save,
             options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX;
         else if (strcasecmp(val + 1, "ads") == 0)
             options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_ADS;
+        else if (strcasecmp(val + 1, "sfm") == 0)
+            options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_SFM;
 #endif
     } else if (optionok(tmp, "options:", val)) {
         char *p;
@@ -1237,7 +1239,7 @@ int               *buflen;
         isad = 0;
         vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime);
 
-    } else if (ad_get_HF_flags( &ad ) & O_CREAT) {
+    } else if (ad_get_MD_flags( &ad ) & O_CREAT) {
         slash = strrchr( vol->v_path, '/' );
         if(slash)
             slash++;
@@ -1249,7 +1251,7 @@ int               *buflen;
                ad_getentrylen( &ad, ADEID_NAME ));
         }
         vol_setdate(vol->v_vid, &ad, st->st_mtime);
-        ad_flush_metadata(&ad);
+        ad_flush(&ad);
     }
     else {
         if (ad_getdate(&ad, AD_DATE_CREATE, &aint) < 0)
@@ -2087,7 +2089,7 @@ int       ibuflen _U_, *rbuflen;
 
     memcpy(&aint, ibuf, sizeof(aint));
     ad_setdate(&ad, AD_DATE_BACKUP, aint);
-    ad_flush(&ad, ADFLAGS_HF);
+    ad_flush(&ad);
     ad_close(&ad, ADFLAGS_HF);
     return( AFP_OK );
 }
@@ -2198,7 +2200,7 @@ static int create_special_folder (const struct vol *vol, const struct _special_f
                        memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr));
                }
 
-               ad_flush( &ad, ADFLAGS_HF );
+               ad_flush( &ad );
                ad_close( &ad, ADFLAGS_HF );
        }
        free(p);
@@ -2277,6 +2279,9 @@ static int savevoloptions (const struct vol *vol)
         case AD_VERSION1_ADS:
             strlcat(buf, "ADOUBLE_VER:ads\n", sizeof(buf));
             break;
+        case AD_VERSION1_SFM:
+            strlcat(buf, "ADOUBLE_VER:sfm\n", sizeof(buf));
+            break;
     }
 
     strlcat(buf, "CNIDBACKEND:", sizeof(buf));
index d71eb05a18cf6bc1e54d8592873091f1ed3509a0..17f02c53554308b3faf877d24951c22dc4e6a6e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.30 2006-09-19 23:00:50 didg Exp $
+ * $Id: adouble.h,v 1.31 2006-09-29 09:39:16 didg Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
 
 /* version info */
 #define AD_VERSION1    0x00010000
+#define SFM_VERSION     AD_VERSION1
+
 #define AD_VERSION2    0x00020000
 #define AD_VERSION2_OSX        0x00020001
 #define AD_VERSION1_ADS        0x00010002
+#define AD_VERSION1_SFM        0x00010003
 #define AD_VERSION     AD_VERSION2
 
 /*
 #define ADEID_PRIVINO           17
 #define ADEID_PRIVSYN           18 /* in synch with database */
 #define ADEID_PRIVID            19
+#define ADEID_SFMRESERVE1       20
+#define ADEID_SFMRESERVE2       21
 
 #define AD_DEV                  0x80444556
 #define AD_INO                  0x80494E4F
 #define AD_SYN                  0x8053594E
 #define AD_ID                   0x8053567E
-#define ADEID_MAX              20
+#define ADEID_MAX              22
 #endif
 
 /* magic */
 #define AD_APPLEDOUBLE_MAGIC 0x00051607
 #define AD_MAGIC            AD_APPLEDOUBLE_MAGIC
 
+#define SFM_MAGIC            0x00504641 
 
 /* sizes of relevant entry bits */
 #define ADEDLEN_MAGIC       4
 #define ADEID_NUM_V1         5
 #define ADEID_NUM_V2         13
 
+// #define ADEID_NUM_SFM        5
+/* sizeof SFM meta data */
+#define AD_SFM_LEN 60  
+
 /* 589 */
 #define AD_DATASZ1      (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT +ADEDLEN_FILEI +ADEDLEN_FINDERI+\
 ADEID_NUM_V1*AD_ENTRY_LEN)
@@ -239,14 +249,22 @@ struct ad_fd {
     int          adf_refcount, adf_lockcount, adf_lockmax;
 };
 
+/* fork attribute */
+#define ATTRBIT_DOPEN     (1<<3)  /* data fork already open */
+#define ATTRBIT_ROPEN     (1<<4)  /* resource fork already open */
+
 /* some header protection */
 #define AD_INITED  0xad494e54  /* ad"INT" */
+struct adouble_fops;
+
 struct adouble {
     u_int32_t          ad_magic;
     u_int32_t          ad_version;
     char               ad_filler[ 16 ];
     struct ad_entry    ad_eid[ ADEID_MAX ];
-    struct ad_fd       ad_df, ad_hf;
+    struct ad_fd       ad_data_fork, ad_resource_fork, ad_metadata_fork;
+    struct ad_fd       *ad_md; /* either ad_resource or ad_metadata */
+
     int                 ad_flags;
     unsigned int        ad_inited;
     int                 ad_options;
@@ -256,9 +274,10 @@ struct adouble {
                                      */
     char                *ad_m_name;   /* mac name for open fork */
     int                 ad_m_namelen;
+    struct adouble_fops        *ad_ops;
 
-    char                *(*ad_path)(const char *, int);
-    int                 (*ad_mkrf)(char *);
+
+    u_int16_t          ad_open_forks;      /* open forks (by others) */
                            
 #ifdef USE_MMAPPED_HEADERS
     char                *ad_data;
@@ -267,13 +286,28 @@ struct adouble {
 #endif
 };
 
+struct adouble_fops {
+    char                *(*ad_path)(const char *, int);
+    int                 (*ad_mkrf)(char *);
+
+    int                (*ad_rebuild_header)(struct adouble *);
+    int                        (*ad_check_header)(struct adouble *, struct stat *);
+    int                        (*ad_header_read)(struct adouble *, struct stat *);
+
+    int                        (*ad_header_upgrade)(struct adouble *, char *);
+
+};
+
 #define ADFLAGS_DF       (1<<0)
-#define ADFLAGS_HF       (1<<1)
+#define ADFLAGS_HF       (1<<1)  
 #define ADFLAGS_DIR      (1<<2)
 #define ADFLAGS_NOADOUBLE (1<<3)
 #define ADFLAGS_V1COMPAT  (1<<4)
 #define ADFLAGS_NOHF      (1<<5)  /* not an error if no ressource fork */
 #define ADFLAGS_RDONLY    (1<<6)  /* don't try readwrite */
+#define ADFLAGS_OPENFORKS (1<<7)  /* check for open fork in ad_metadata function */
+#define ADFLAGS_RF       (1<<8) 
+#define ADFLAGS_MD       ADFLAGS_HF /* (1<<9) */
 
 /* adouble v2 cnid cache */
 #define ADVOL_NODEV      (1 << 0)   
@@ -363,8 +397,10 @@ struct adouble {
 #define AD_AFPFILEI_GROUP       (1 << 1) /* ignore group */
 #define AD_AFPFILEI_BLANKACCESS (1 << 2) /* blank access permissions */
 
-#define ad_dfileno(ad)         ((ad)->ad_df.adf_fd)
-#define ad_hfileno(ad)         ((ad)->ad_hf.adf_fd)
+#define ad_data_fileno(ad)     ((ad)->ad_data_fork.adf_fd)
+#define ad_reso_fileno(ad)     ((ad)->ad_resource_fork.adf_fd)
+#define ad_meta_fileno(ad)     ((ad)->ad_md->adf_fd)
+
 #define ad_getversion(ad)      ((ad)->ad_version)
 
 #define ad_getentrylen(ad,eid) ((ad)->ad_eid[(eid)].ade_len)
@@ -373,14 +409,17 @@ struct adouble {
 #define ad_getentryoff(ad,eid)  ((ad)->ad_eid[(eid)].ade_off)
 #define ad_entry(ad,eid)        ((caddr_t)(ad)->ad_data + \
                                 (ad)->ad_eid[(eid)].ade_off)     
-#define ad_getoflags(ad,adf)   (((adf)&ADFLAGS_HF) ? \
-       (ad)->ad_hf.adf_flags : (ad)->ad_df.adf_flags)
 
-#define ad_get_HF_flags(ad)    ((ad)->ad_hf.adf_flags)
+#define ad_get_HF_flags(ad)    ((ad)->ad_resource_fork.adf_flags)
+#define ad_get_MD_flags(ad)    ((ad)->ad_md->adf_flags)
+
+/* ad_flush.c 
+
+*/
+extern int ad_rebuild_adouble_header __P((struct adouble *));
+extern int ad_rebuild_sfm_header __P((struct adouble *));
 
-/* ad_flush.c */
-extern void ad_rebuild_header __P((struct adouble *));
-extern int ad_flush           __P((struct adouble *, int));
+extern int ad_flush           __P((struct adouble *));
 extern int ad_close           __P((struct adouble *, int));
 
 /* ad_lock.c */
@@ -408,6 +447,7 @@ extern char *ad_dir       __P((const char *));
 extern char *ad_path      __P((const char *, int));
 extern char *ad_path_osx  __P((const char *, int));
 extern char *ad_path_ads  __P((const char *, int));
+extern char *ad_path_sfm  __P((const char *, int));
 
 extern int ad_mode        __P((const char *, int));
 extern int ad_mkdir       __P((const char *, int));
@@ -419,10 +459,9 @@ extern int ad_stat        __P((const char *, struct stat *));
 extern int ad_metadata    __P((const char *, int, struct adouble *));
 
 #define ad_open_metadata(name, flags, mode, adp)\
-   ad_open(name, ADFLAGS_HF|(flags), O_RDWR |(mode), 0666, (adp))
+   ad_open(name, ADFLAGS_MD|(flags), O_RDWR |(mode), 0666, (adp))
 
-#define ad_flush_metadata(adp) ad_flush( (adp), ADFLAGS_HF)
-#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_HF)
+#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_MD)
 
 /* build a resource fork mode from the data fork mode:
  * remove X mode and extend header to RW if R or W (W if R for locking),
index 7168f8fecb5ba0da972bc872efb3fec336f55ce4..e95e36e647c9533b096bd347572f26e6ddd39c86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_attr.c,v 1.5 2005-04-28 20:49:51 bfernhomberg Exp $
+ * $Id: ad_attr.c,v 1.6 2006-09-29 09:39:16 didg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -33,12 +33,17 @@ int ad_getattr(const struct adouble *ad, u_int16_t *attr)
    else 
       return -1;
 
+   *attr |= htons(ad->ad_open_forks);
+
    return 0;
 }
 
 /* ----------------- */
-int ad_setattr(const struct adouble *ad, const u_int16_t attr)
+int ad_setattr(const struct adouble *ad, const u_int16_t attribute)
 {
+   /* we don't save open forks indicator */
+   u_int16_t attr = attribute & ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
+
    if (ad->ad_version == AD_VERSION1) {
        if (ad_getentryoff(ad, ADEID_FILEI)) {
            memcpy(ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, &attr,
@@ -107,7 +112,7 @@ char   temp[ADEDLEN_PRIVSYN];
      * note inode and device are opaques and not in network order
      * only use the ID if adouble is writable for us.
     */
-    if (adp && ( adp->ad_options & ADVOL_CACHE) && ( adp->ad_hf.adf_flags & O_RDWR )
+    if (adp && ( adp->ad_options & ADVOL_CACHE) && ( adp->ad_md->adf_flags & O_RDWR )
             && sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)
             && sizeof(ino_t) == ad_getentrylen(adp,ADEID_PRIVINO)
             && sizeof(temp) == ad_getentrylen(adp,ADEID_PRIVSYN)
index 6324679be57ff7ed8692a0525597120730af601c..c3ab1b7738818e126baf0ae51980fa14a5bc5ff6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_date.c,v 1.4 2005-04-28 20:49:51 bfernhomberg Exp $
+ * $Id: ad_date.c,v 1.5 2006-09-29 09:39:16 didg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -19,6 +19,10 @@ int ad_setdate(const struct adouble *ad,
     date = AD_DATE_FROM_UNIX(date);
 
   if (ad->ad_version == AD_VERSION1) {
+
+    if (!ad_getentryoff(ad, ADEID_FILEI))
+        return -1;
+
     if (dateoff > AD_DATE_BACKUP)
       return -1;
     memcpy(ad_entry(ad, ADEID_FILEI) + dateoff, &date, sizeof(date));
@@ -46,6 +50,8 @@ int ad_getdate(const struct adouble *ad,
   if (ad->ad_version == AD_VERSION1) {
     if (dateoff > AD_DATE_BACKUP)
       return -1;
+    if (!ad_getentryoff(ad, ADEID_FILEI))
+        return -1;
     memcpy(date, ad_entry(ad, ADEID_FILEI) + dateoff, sizeof(u_int32_t));
 
   } else if (ad->ad_version == AD_VERSION2) {
index c92daddffeee738a3b58013957f048975ddf2ed8..7cef3f7e0ddbfdf1606e7c27870f179d9b16f747 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_flush.c,v 1.7 2005-04-28 20:49:52 bfernhomberg Exp $
+ * $Id: ad_flush.c,v 1.8 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
 #include <config.h>
 #endif /* HAVE_CONFIG_H */
 
+#include <string.h>
 #include <atalk/adouble.h>
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <errno.h>
 
 #include "ad_private.h"
@@ -50,8 +50,10 @@ AD_DEV, AD_INO, AD_SYN, AD_ID
 #define EID_DISK(a) (set_eid[a])
 #endif
 
-/* rebuild the header */
-void ad_rebuild_header(struct adouble *ad)
+/* rebuild the adouble header 
+ * XXX should be in a separate file ?
+*/
+int  ad_rebuild_adouble_header(struct adouble *ad)
 {
     u_int32_t          eid;
     u_int32_t          temp;
@@ -96,16 +98,83 @@ void ad_rebuild_header(struct adouble *ad)
     }
     nent = htons( nent );
     memcpy(nentp, &nent, sizeof( nent ));
+    return ad_getentryoff(ad, ADEID_RFORK);
+}
+
+/* ------------------- 
+ * XXX copy only header with same size or comment
+ * doesn't work well for adouble with different version.
+ * 
+*/
+int ad_copy_header(struct adouble *add, struct adouble *ads)
+{
+    u_int32_t          eid;
+    int                        len;
+
+    for ( eid = 0; eid < ADEID_MAX; eid++ ) {
+      if ( ads->ad_eid[ eid ].ade_off == 0 ) {
+       continue;
+      }
+
+      if ( add->ad_eid[ eid ].ade_off == 0 ) {
+       continue;
+      }
+
+      len = ads->ad_eid[ eid ].ade_len;
+      if (!len) {
+       continue;
+      }
+      
+      if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) {
+       continue;      
+      }
+      
+      ad_setentrylen( add, eid, len );
+      memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
+    }
+    add->ad_rlen = ads->ad_rlen;
+    return 0;
 }
 
+/* ------------------- */
+int  ad_rebuild_sfm_header(struct adouble *ad)
+{
+    u_int32_t          eid;
+    u_int32_t          temp;
+    
+    u_int16_t          attr;
+    char               *buf, *nentp;
 
-int ad_flush( ad, adflags )
+    /*
+     * Rebuild any header information that might have changed.
+     */
+    buf = ad->ad_data;
+    /* FIXME */
+//    temp = htonl( ad->ad_magic );
+    temp = ad->ad_magic;
+    memcpy(buf, &temp, sizeof( temp ));
+    
+//    temp = htonl( ad->ad_version );
+    temp = ad->ad_version;
+    memcpy(buf +4, &temp, sizeof( temp ));
+
+    /* need to save attrib */
+    if (!ad_getattr(ad, &attr)) {
+        attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
+
+        memcpy(buf +48 +4, &attr, sizeof(attr));
+        
+    }
+    return AD_SFM_LEN;
+}
+
+
+int ad_flush( ad )
     struct adouble     *ad;
-    int                        adflags;
 {
     int len;
 
-    if (( adflags & ADFLAGS_HF ) && ( ad->ad_hf.adf_flags & O_RDWR )) {
+    if (( ad->ad_md->adf_flags & O_RDWR )) {
        /* sync our header */
         if (ad->ad_rlen > 0xffffffff) {
             ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
@@ -113,10 +182,9 @@ int ad_flush( ad, adflags )
         else {
             ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
         }
-        ad_rebuild_header(ad);
-       len = ad_getentryoff(ad, ADEID_RFORK);
-       /* now flush it out */
-        if (adf_pwrite(&ad->ad_hf, ad->ad_data, len, 0) != len) {
+        len = ad->ad_ops->ad_rebuild_header(ad);
+
+        if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
            if ( errno == 0 ) {
                errno = EIO;
            }
@@ -134,23 +202,44 @@ int ad_close( ad, adflags )
 {
     int                        err = 0;
 
-    if (( adflags & ADFLAGS_DF ) && ad->ad_df.adf_fd != -1 &&
-           !(--ad->ad_df.adf_refcount)) {
-       if ( close( ad->ad_df.adf_fd ) < 0 ) {
+    if (( adflags & ADFLAGS_DF ) && ad_data_fileno(ad) != -1 &&
+           !(--ad->ad_data_fork.adf_refcount)) {
+       if ( close( ad_data_fileno(ad) ) < 0 ) {
            err = -1;
        }
-       ad->ad_df.adf_fd = -1;
-       adf_lock_free(&ad->ad_df);
+       ad_data_fileno(ad) = -1;
+       adf_lock_free(&ad->ad_data_fork);
     }
 
-    if (( adflags & ADFLAGS_HF ) && ad->ad_hf.adf_fd != -1 &&
-           !(--ad->ad_hf.adf_refcount)) {
-       if ( close( ad->ad_hf.adf_fd ) < 0 ) {
+    if (!( adflags & ADFLAGS_HF )) {
+        return err;
+    }
+    
+    /* meta /resource fork */
+
+    if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
+       if ( close( ad_meta_fileno(ad) ) < 0 ) {
            err = -1;
        }
-       ad->ad_hf.adf_fd = -1;
-       adf_lock_free(&ad->ad_hf);
+       ad_meta_fileno(ad) = -1;
+       adf_lock_free(ad->ad_md);
     }
 
-    return( err );
+    if (ad->ad_flags != AD_VERSION1_SFM) {
+       return err;
+    }
+
+    if ((adflags & ADFLAGS_DIR)) {
+       return err;
+    }
+
+    if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
+       if ( close( ad_reso_fileno(ad) ) < 0 ) {
+           err = -1;
+       }
+       ad_reso_fileno(ad) = -1;
+       adf_lock_free(&ad->ad_resource_fork);
+    }
+    
+    return err;
 }
index 77cd502526c9ead25e7cce94b611d622050deef1..31e8c71a476fe38bbf82e88abd0018df470ea502 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: ad_lock.c,v 1.12 2005-04-28 20:49:52 bfernhomberg Exp $
+ * $Id: ad_lock.c,v 1.13 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1998,1999 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved. See COPYRIGHT for more information.
@@ -261,27 +261,31 @@ int ad_fcntl_lock(struct adouble *ad, const u_int32_t eid, const int locktype,
   lock.l_start = off;
   type = locktype;
   if (eid == ADEID_DFORK) {
-    adf = &ad->ad_df;
+    adf = &ad->ad_data_fork;
     if ((type & ADLOCK_FILELOCK)) {
-        if (ad_hfileno(ad) != -1) {
+        if (ad_meta_fileno(ad) != -1) { /* META */
+            adf = ad->ad_md;
             lock.l_start = df2off(off);
-            adf = &ad->ad_hf;
         }
     }
   } else { /* rfork */
-    adf = &ad->ad_hf;
-    if (adf->adf_fd == -1) {
-        /* there's no resource fork. return a lock error
+    if (ad_meta_fileno(ad) == -1 || ad_reso_fileno(ad) == -1) {
+        /* there's no meta data. return a lock error 
          * otherwise if a second process is able to create it
          * locks are a mess.
          */
         errno = EACCES;
         return -1;
     }
-    if (type & ADLOCK_FILELOCK) 
+    if (type & ADLOCK_FILELOCK) {
+      adf = ad->ad_md;                 /* either resource or meta data (set in ad_open) */
       lock.l_start = hf2off(off);
-    else
+    }
+    else {
+      /* we really want the resource fork it's a byte lock */
+      adf = &ad->ad_resource_fork;
       lock.l_start += ad_getentryoff(ad, eid);
+    }
   }
   /* NOTE: we can't write lock a read-only file. on those, we just
     * make sure that we have a read lock set. that way, we at least prevent
@@ -399,18 +403,18 @@ int ad_testlock(struct adouble *ad, int eid, const off_t off)
 
   lock.l_start = off;
   if (eid == ADEID_DFORK) {
-    adf = &ad->ad_df;
-    if ((ad_hfileno(ad) != -1)) {
-       adf = &ad->ad_hf;
+    adf = &ad->ad_data_fork;
+    if ((ad_meta_fileno(ad) != -1)) {
+       adf = ad->ad_md;
        lock.l_start = df2off(off);
     }
   } 
   else { /* rfork */
-    if ((ad_hfileno(ad) == -1)) {
+    if ((ad_meta_fileno(ad) == -1)) {
         /* there's no resource fork. return no lock */
         return 0;
     }
-    adf = &ad->ad_hf;
+    adf = ad->ad_md;
     lock.l_start = hf2off(off);
   }
 
@@ -448,9 +452,10 @@ int ad_fcntl_tmplock(struct adouble *ad, const u_int32_t eid, const int locktype
   lock.l_start = off;
   type = locktype;
   if (eid == ADEID_DFORK) {
-    adf = &ad->ad_df;
+    adf = &ad->ad_data_fork;
   } else {
-    adf = &ad->ad_hf;
+    /* FIXME META */
+    adf = &ad->ad_resource_fork;
     if (adf->adf_fd == -1) {
         /* there's no resource fork. return success */
         return 0;
@@ -515,9 +520,9 @@ int ad_excl_lock(struct adouble *ad, const u_int32_t eid)
   lock.l_len = 0;
 
   if (eid == ADEID_DFORK) {
-    adf = &ad->ad_df;
+    adf = &ad->ad_data_fork;
   } else {
-    adf = &ad->ad_hf;
+    adf = &ad->ad_resource_fork;
     lock.l_start = ad_getentryoff(ad, eid);
   }
   
@@ -530,10 +535,18 @@ int ad_excl_lock(struct adouble *ad, const u_int32_t eid)
 /* --------------------- */
 void ad_fcntl_unlock(struct adouble *ad, const int user)
 {
-  if (ad->ad_df.adf_fd != -1) {
-    adf_unlock(&ad->ad_df, user);
+  if (ad_data_fileno(ad) != -1) {
+    adf_unlock(&ad->ad_data_fork, user);
   }
-  if (ad->ad_hf.adf_fd != -1) {
-    adf_unlock(&ad->ad_hf, user);
+  if (ad_reso_fileno(ad) != -1) {
+    adf_unlock(&ad->ad_resource_fork, user);
   }
+
+  if (ad->ad_flags != AD_VERSION1_SFM) {
+    return;
+  }
+  if (ad_meta_fileno(ad) != -1) {
+    adf_unlock(&ad->ad_metadata_fork, user);
+  }
+
 }
index 4d5a2850b1419ae21ef3e24e43afb53532cd2b42..09f2ed3dff1331da03a8878aa64a1f054deba2bb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.36 2006-09-19 23:00:50 didg Exp $
+ * $Id: ad_open.c,v 1.37 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -193,6 +193,15 @@ static const struct entry entry_order_osx[ADEID_NUM_OSX +1] = {
   {0, 0, 0}
 };
 
+#define ADEID_NUM_SFM 3
+static const struct entry entry_order_sfm[ADEID_NUM_SFM +1] = {
+  {ADEID_FINDERI,     16,         ADEDLEN_FINDERI},   /* 9 */
+  {ADEID_SFMRESERVE2, 16+32,      6},                 /* 21 */
+  {ADEID_FILEI,       60,         ADEDLEN_FILEI},     /* 7 */
+
+  {0, 0, 0}
+};
+
 #endif /* AD_VERSION == AD_VERSION2 */
 
 #if AD_VERSION == AD_VERSION2
@@ -213,7 +222,7 @@ static int ad_update(struct adouble *ad, const char *path)
   if (!path || ad->ad_flags != AD_VERSION2)
     return 0;
   
-  if (!(ad->ad_hf.adf_flags & O_RDWR)) {
+  if (!(ad->ad_md->adf_flags & O_RDWR)) {
       /* we were unable to open the file read write the last time */
       return 0;
   }
@@ -235,7 +244,7 @@ static int ad_update(struct adouble *ad, const char *path)
   if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0, 0) < 0)
     goto bail_err;
 
-  fd = ad->ad_hf.adf_fd;
+  fd = ad->ad_md->adf_fd;
 
   if (fstat(fd, &st)) {
     goto bail_lock;
@@ -308,7 +317,7 @@ static int ad_update(struct adouble *ad, const char *path)
 
   /* rebuild the header and cleanup */
   LOG(log_debug, logtype_default, "updated AD2 header %s", path);
-  ad_flush(ad, ADFLAGS_HF );
+  ad_flush(ad );
   ret = 0;
 
 bail_lock:
@@ -336,7 +345,7 @@ static int ad_convert(struct adouble *ad, const char *path)
       return 0;
   }
   
-  if (!(ad->ad_hf.adf_flags & ( O_RDWR))) {
+  if (!(ad->ad_md->adf_flags & ( O_RDWR))) {
       /* we were unable to open the file read write the last time */
       return 0;
   }
@@ -361,7 +370,7 @@ static int ad_convert(struct adouble *ad, const char *path)
     goto bail_err;
 
   /* we reuse fd from the resource fork */
-  fd = ad->ad_hf.adf_fd;
+  fd = ad->ad_md->adf_fd;
 
   if (ad->ad_eid[ADEID_RFORK].ade_off) {
       shiftdata = ADEDOFF_RFORK_V2 -ad->ad_eid[ADEID_RFORK].ade_off;
@@ -466,7 +475,7 @@ static int ad_convert(struct adouble *ad, const char *path)
   memset(ad_entry(ad, ADEID_PRODOSFILEI), 0, ADEDLEN_PRODOSFILEI);
   
   /* rebuild the header and cleanup */
-  ad_flush(ad, ADFLAGS_HF );
+  ad_flush(ad );
   ret = 0;
   
 bail_lock:
@@ -556,7 +565,7 @@ static int ad_header_read(struct adouble *ad, struct stat *hst)
     struct stat         st;
 
     /* read the header */
-    if ((header_len = adf_pread( &ad->ad_hf, buf, sizeof(ad->ad_data), 0)) < 0) {
+    if ((header_len = adf_pread( ad->ad_md, buf, sizeof(ad->ad_data), 0)) < 0) {
        return -1;
     }
     if (header_len < AD_HEADER_LEN) {
@@ -639,7 +648,7 @@ static int ad_header_read(struct adouble *ad, struct stat *hst)
     
     if (hst == NULL) {
         hst = &st;
-        if (fstat(ad->ad_hf.adf_fd, &st) < 0) {
+        if (fstat(ad->ad_md->adf_fd, &st) < 0) {
            return 1; /* fail silently */
         }
     }
@@ -664,6 +673,115 @@ static int ad_header_read(struct adouble *ad, struct stat *hst)
     return 0;
 }
 
+/* ---------------------------
+   SFM structure 
+ */
+#if 0
+typedef struct {
+    byte    afpi_Signature[4];      /* Must be 0x00504641 */
+    byte    afpi_Version[4];        /* Must be 0x00010000 */
+    byte    afpi_Reserved1[4];
+    byte    afpi_BackupTime[4];     /* Backup time for the file/dir */
+    byte    finderinfo[32];         /* Finder info */
+    byte    afpi_ProDosInfo[6];     /* ProDos Info */
+    byte    afpi_Reserved2[6];
+} sfm_info; 
+#endif
+
+static int ad_header_sfm_read(struct adouble *ad, struct stat *hst)
+{
+    char                *buf = ad->ad_data;
+    const struct entry  *eid;
+    u_int16_t           nentries;
+    int                 len;
+    ssize_t             header_len;
+    static int          warning = 0;
+    struct stat         st;
+
+    /* read the header */
+    if ((header_len = adf_pread( ad->ad_md, buf, sizeof(ad->ad_data), 0)) < 0) {
+       return -1;
+    }
+    if (header_len != AD_SFM_LEN) {
+        errno = EIO;
+        return -1;
+    }
+
+    memcpy(&ad->ad_magic, buf, sizeof( ad->ad_magic ));
+    memcpy(&ad->ad_version, buf + 4, sizeof( ad->ad_version ));
+
+    /* FIXME in the the great Microsoft tradition they aren't in network order */
+#if 0
+    if (ad->ad_magic == SFM_MAGIC && ad->ad_version == AD_VERSION1) {
+      if (!warning) {
+       LOG(log_debug, logtype_default, "notice: fixing up byte-swapped v1 magic/version.");
+       warning++;
+      }
+
+    } else {
+      ad->ad_magic = ntohl( ad->ad_magic );
+      ad->ad_version = ntohl( ad->ad_version );
+    }
+#endif
+    if ((ad->ad_magic != SFM_MAGIC) || ((ad->ad_version != AD_VERSION1) )) {
+      errno = EIO;
+      LOG(log_debug, logtype_default, "ad_header_sfm_read: can't parse AppleDouble header.");
+      return -1;
+    }
+
+    /* reinit adouble table */
+    eid = entry_order_sfm;
+    while (eid->id) {
+        ad->ad_eid[eid->id].ade_off = eid->offset;
+       ad->ad_eid[eid->id].ade_len = eid->len;
+       eid++;
+    }
+
+    /* steal some prodos for attribute */
+    {
+    
+        u_int16_t attribute;
+        memcpy(&attribute, buf + 48 +4, sizeof(attribute));
+        ad_setattr(ad, attribute );
+    }
+    
+    if (ad->ad_resource_fork.adf_fd != -1) {
+        /* we have a resource fork use it rather than the metadata */
+        if (fstat(ad->ad_resource_fork.adf_fd, &st) < 0) {
+            /* XXX set to zero ?
+            ad->ad_rlen =  0;
+            */
+            return 1;
+        }
+        ad->ad_rlen = st.st_size;
+        hst = &st;
+    }
+    else if (hst == NULL) {
+        hst = &st;
+        if (fstat(ad->ad_md->adf_fd, &st) < 0) {
+           return 1; /* fail silently */
+       }
+    }
+
+    /* fix up broken dates */
+    if (ad->ad_version == AD_VERSION1) {
+      u_int32_t aint;
+      
+      /* check to see if the ad date is wrong. just see if we have
+      * a modification date in the future. */
+      if (((ad_getdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, &aint)) == 0) &&
+         (aint > TIMEWARP_DELTA + hst->st_mtime)) {
+       ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, aint - AD_DATE_DELTA);
+       ad_getdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, &aint);
+       ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, aint - AD_DATE_DELTA);
+       ad_getdate(ad, AD_DATE_BACKUP | AD_DATE_UNIX, &aint);
+       ad_setdate(ad, AD_DATE_BACKUP | AD_DATE_UNIX, aint - AD_DATE_DELTA);
+      }
+    }
+
+    return 0;
+}
+
 /* ---------------------------------------
  * Put the .AppleDouble where it needs to be:
  *
@@ -802,14 +920,49 @@ ad_path_ads( path, adflags )
     strlcat( pathbuf, slash, MAXPATHLEN +1);
 
     strlcat( pathbuf, "/Afp_AfpInfo", MAXPATHLEN +1);
+    return( pathbuf );
+}
 
-#if 0
-    if ((adflags & ADFLAGS_HF)) {
-        strlcat( pathbuf, "Afp_AfpInfo", MAXPATHLEN +1);
+/* ---------------------- 
+ * mostly the same as ads, only case change Afp --> AFP and AFP_Resoure
+*/
+char *
+ad_path_sfm( path, adflags )
+    const char *path;
+    int                adflags;
+{
+    static char        pathbuf[ MAXPATHLEN + 1];
+    char       c, *slash, buf[MAXPATHLEN + 1];
+    size_t      l;
+
+    l = strlcpy(buf, path, MAXPATHLEN +1);
+    if ( adflags & ADFLAGS_DIR ) {
+       strcpy( pathbuf, buf);
+       if ( *buf != '\0' && l < MAXPATHLEN) {
+           pathbuf[l++] = '/';
+           pathbuf[l] = 0;
+       }
+       slash = ".Parent";
+    } else {
+       if (NULL != ( slash = strrchr( buf, '/' )) ) {
+           c = *++slash;
+           *slash = '\0';
+           strcpy( pathbuf, buf);
+           *slash = c;
+       } else {
+           pathbuf[ 0 ] = '\0';
+           slash = buf;
+       }
+    }
+    strlcat( pathbuf, ".AppleDouble/", MAXPATHLEN +1);
+    strlcat( pathbuf, slash, MAXPATHLEN +1);
+
+    if ((adflags == ADFLAGS_RF)) {
+        strlcat( pathbuf, "/AFP_Resource", MAXPATHLEN +1);
+    }
     else {
-        strlcat( pathbuf, "Afp_Resource", MAXPATHLEN +1);
+        strlcat( pathbuf, "/AFP_AfpInfo", MAXPATHLEN +1);
     }
-#endif      
     return( pathbuf );
 }
 
@@ -1025,21 +1178,97 @@ static int new_rfork(const char *path, struct adouble *ad, int adflags);
 #define AD_SET(a) a = 0
 #endif
 
+/* --------------------------- */
+static int ad_check_size(struct adouble *ad, struct stat *st)
+{
+   if (st->st_size > 0 && st->st_size < AD_DATASZ1) 
+       return 1;
+   return 0;
+}
+
+/* --------------------------- */
+static int ad_check_size_sfm(struct adouble *ad, struct stat *st)
+{
+   if (st->st_size > 0 && st->st_size < AD_SFM_LEN) 
+       return 1;
+   return 0;
+}
+
+/* --------------------------- */
+static int ad_header_upgrade(struct adouble *ad, char *name)
+{
+#if AD_VERSION == AD_VERSION2
+    int ret;
+    if ( (ret = ad_convert(ad, name)) < 0 || (ret = ad_update(ad, name) < 0)) {
+       return ret;
+    }
+#endif
+    return 0;
+}
+
+/* --------------------------- */
+static int ad_header_upgrade_none(struct adouble *ad, char *name)
+{
+    return 0;
+}
+
+/* --------------------------- */
+static struct adouble_fops ad_osx = {
+        &ad_path_osx,
+        &ad_mkrf_osx,
+        &ad_rebuild_adouble_header,
+        &ad_check_size,
+
+        &ad_header_read,
+        &ad_header_upgrade,        
+};
+
+static struct adouble_fops ad_ads = {
+        &ad_path_ads,
+        &ad_mkrf_ads,
+        &ad_rebuild_adouble_header,
+        &ad_check_size,
+
+        &ad_header_read,
+        &ad_header_upgrade,        
+};
+
+static struct adouble_fops ad_sfm = {
+        &ad_path_sfm,
+        &ad_mkrf_ads,
+        &ad_rebuild_sfm_header,
+        &ad_check_size_sfm,
+        
+        &ad_header_sfm_read,
+        &ad_header_upgrade_none,
+};
+
+static struct adouble_fops ad_adouble = {
+        &ad_path,
+        &ad_mkrf,
+        &ad_rebuild_adouble_header,
+        &ad_check_size,
+
+        &ad_header_read,
+        &ad_header_upgrade,        
+};
+
+
 void ad_init(struct adouble *ad, int flags, int options)
 {
     memset( ad, 0, sizeof( struct adouble ) );
     ad->ad_flags = flags;
     if (flags == AD_VERSION2_OSX) {
-        ad->ad_path = ad_path_osx;
-        ad->ad_mkrf = ad_mkrf_osx;
+        ad->ad_ops = &ad_osx;
     }
     else if (flags == AD_VERSION1_ADS) {
-        ad->ad_path = ad_path_ads;
-        ad->ad_mkrf = ad_mkrf_ads;
+        ad->ad_ops = &ad_ads;
+    }
+    else if (flags == AD_VERSION1_SFM) {
+        ad->ad_ops = &ad_sfm;
     }
     else {
-        ad->ad_path = ad_path;
-        ad->ad_mkrf = ad_mkrf;
+        ad->ad_ops = &ad_adouble;
     }
     ad->ad_options = options;
 }
@@ -1053,52 +1282,69 @@ int ad_open( path, adflags, oflags, mode, ad )
     int                        adflags, oflags, mode;
     struct adouble     *ad;
 {
-    struct stat         st;
+    struct stat         st_dir;
+    struct stat         st_meta;
+    struct stat         *pst = NULL;
     char               *ad_p;
     int                        hoflags, admode;
     int                 st_invalid = -1;
     int                 open_df = 0;
     
     if (ad->ad_inited != AD_INITED) {
-        ad_dfileno(ad) = -1;
-        ad_hfileno(ad) = -1;
-       adf_lock_init(&ad->ad_df);
-       adf_lock_init(&ad->ad_hf);
+        ad_data_fileno(ad) = -1;
+        ad_reso_fileno(ad) = -1;
+       adf_lock_init(&ad->ad_data_fork);
+       adf_lock_init(&ad->ad_resource_fork);
+       if (ad->ad_flags != AD_VERSION1_SFM) {
+               ad->ad_md = &ad->ad_resource_fork;
+       }
+       else {
+               adf_lock_init(&ad->ad_metadata_fork);
+               ad->ad_md = &ad->ad_metadata_fork;
+               ad_meta_fileno(ad) = -1;
+       }
         ad->ad_inited = AD_INITED;
         ad->ad_refcount = 1;
+        ad->ad_open_forks = 0;
+    }
+    else {
+       ad->ad_open_forks = ((ad->ad_data_fork.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
+       /* XXX not true if we have a meta data fork ? */
+       if ((ad->ad_resource_fork.adf_refcount > ad->ad_data_fork.adf_refcount))
+               ad->ad_open_forks |= ATTRBIT_ROPEN;
     }
 
     if ((adflags & ADFLAGS_DF)) { 
-        if (ad_dfileno(ad) == -1) {
+        if (ad_data_fileno(ad) == -1) {
          hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
          admode = mode;
          if ((oflags & O_CREAT)) {
-             st_invalid = ad_mode_st(path, &admode, &st);
+             st_invalid = ad_mode_st(path, &admode, &st_dir);
              if ((ad->ad_options & ADVOL_UNIXPRIV)) {
                  admode = mode;
              }
          }
-          ad->ad_df.adf_fd =open( path, hoflags, admode );
-         if (ad->ad_df.adf_fd < 0 ) {
+          ad->ad_data_fork.adf_fd =open( path, hoflags, admode );
+         if (ad->ad_data_fork.adf_fd < 0 ) {
              if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
                 hoflags = oflags;
-                ad->ad_df.adf_fd = open( path, hoflags, admode );
+                ad->ad_data_fork.adf_fd = open( path, hoflags, admode );
              }
          }
-         if ( ad->ad_df.adf_fd < 0)
+         if ( ad->ad_data_fork.adf_fd < 0)
                return -1;
 
-         AD_SET(ad->ad_df.adf_off);
-         ad->ad_df.adf_flags = hoflags;
+         AD_SET(ad->ad_data_fork.adf_off);
+         ad->ad_data_fork.adf_flags = hoflags;
          if (!st_invalid) {
              /* just created, set owner if admin (root) */
-             ad_chown(path, &st);
+             ad_chown(path, &st_dir);
          }
        } 
         else {
             /* the file is already open... but */
             if ((oflags & ( O_RDWR | O_WRONLY)) &&             /* we want write access */
-               !(ad->ad_df.adf_flags & ( O_RDWR | O_WRONLY))) /* and it was denied the first time */
+               !(ad->ad_data_fork.adf_flags & ( O_RDWR | O_WRONLY))) /* and it was denied the first time */
             {
                  errno = EACCES;
                  return -1;
@@ -1112,15 +1358,17 @@ int ad_open( path, adflags, oflags, mode, ad )
             */
        }
        open_df = ADFLAGS_DF;
-       ad->ad_df.adf_refcount++;
+       ad->ad_data_fork.adf_refcount++;
     }
 
     if (!(adflags & ADFLAGS_HF)) 
         return 0;
+
+    /* ****************************************** */
         
-    if (ad_hfileno(ad) != -1) { /* the file is already open */
+    if (ad_meta_fileno(ad) != -1) { /* the file is already open */
         if ((oflags & ( O_RDWR | O_WRONLY)) &&             
-               !(ad->ad_hf.adf_flags & ( O_RDWR | O_WRONLY))) {
+               !(ad->ad_md->adf_flags & ( O_RDWR | O_WRONLY))) {
            if (open_df) {
                 /* don't call with ADFLAGS_HF because we didn't open ressource fork */
                ad_close( ad, open_df );
@@ -1129,25 +1377,25 @@ int ad_open( path, adflags, oflags, mode, ad )
            return -1;
        }
        ad_refresh(ad);
-       ad->ad_hf.adf_refcount++;
-       return 0;
+       ad->ad_md->adf_refcount++;
+       goto sfm;
     }
 
-    ad_p = ad->ad_path( path, adflags );
+    ad_p = ad->ad_ops->ad_path( path, adflags );
 
     hoflags = oflags & ~O_CREAT;
     if (!(adflags & ADFLAGS_RDONLY)) {
         hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
     }
-    ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 );
-    if (ad->ad_hf.adf_fd < 0 ) {
+    ad->ad_md->adf_fd = open( ad_p, hoflags, 0 );
+    if (ad->ad_md->adf_fd < 0 ) {
         if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
             hoflags = oflags & ~O_CREAT;
-            ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 );
+            ad->ad_md->adf_fd = open( ad_p, hoflags, 0 );
         }    
     }
 
-    if ( ad->ad_hf.adf_fd < 0 ) { 
+    if ( ad->ad_md->adf_fd < 0 ) { 
         if (errno == ENOENT && (oflags & O_CREAT) ) {
            /*
             * We're expecting to create a new adouble header file,
@@ -1156,47 +1404,47 @@ int ad_open( path, adflags, oflags, mode, ad )
             */
            admode = mode;
            errno = 0;
-           st_invalid = ad_mode_st(ad_p, &admode, &st);
+           st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
            if ((ad->ad_options & ADVOL_UNIXPRIV)) {
                admode = mode;
            }
            admode = ad_hf_mode(admode); 
            if ( errno == ENOENT && !(adflags & ADFLAGS_NOADOUBLE) && ad->ad_flags != AD_VERSION2_OSX) {
-               if (ad->ad_mkrf( ad_p) < 0) {
+               if (ad->ad_ops->ad_mkrf( ad_p) < 0) {
                    return ad_error(ad, adflags);
                }
                admode = mode;
-               st_invalid = ad_mode_st(ad_p, &admode, &st);
+               st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
                if ((ad->ad_options & ADVOL_UNIXPRIV)) {
                    admode = mode;
                }
                admode = ad_hf_mode(admode); 
            }
            /* retry with O_CREAT */
-           ad->ad_hf.adf_fd = open( ad_p, oflags,admode );
-           if ( ad->ad_hf.adf_fd < 0 ) {
+           ad->ad_md->adf_fd = open( ad_p, oflags,admode );
+           if ( ad->ad_md->adf_fd < 0 ) {
                return ad_error(ad, adflags);
            }
-           ad->ad_hf.adf_flags = oflags;
+           ad->ad_md->adf_flags = oflags;
            /* just created, set owner if admin owner (root) */
            if (!st_invalid) {
-               ad_chown(ad_p, &st);
+               ad_chown(ad_p, &st_dir);
            }
        }
        else {
            return ad_error(ad, adflags);
        }
-    } else if (fstat(ad->ad_hf.adf_fd, &st) == 0 && st.st_size == 0) {
+    } else if (fstat(ad->ad_md->adf_fd, &st_meta) == 0 && st_meta.st_size == 0) {
        /* for 0 length files, treat them as new. */
-       ad->ad_hf.adf_flags = hoflags| O_TRUNC;
+       ad->ad_md->adf_flags = hoflags| O_TRUNC;
     } else {
-        ad->ad_hf.adf_flags = hoflags;
+        ad->ad_md->adf_flags = hoflags;
     }
-    AD_SET(ad->ad_hf.adf_off);
+    AD_SET(ad->ad_md->adf_off);
          
     memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
-    ad->ad_hf.adf_refcount++;
-    if ((ad->ad_hf.adf_flags & ( O_TRUNC | O_CREAT ))) {
+    ad->ad_md->adf_refcount++;
+    if ((ad->ad_md->adf_flags & ( O_TRUNC | O_CREAT ))) {
         /*
          * This is a new adouble header file. Initialize the structure,
          * instead of reading it.
@@ -1209,12 +1457,10 @@ int ad_open( path, adflags, oflags, mode, ad )
            return -1;
        }
     } else {
-           /* Read the adouble header in and parse it.*/
-       if ((ad_header_read( ad , &st) < 0)
-#if AD_VERSION == AD_VERSION2
-               || (ad_convert(ad, ad_p) < 0) || (ad_update(ad, ad_p) < 0)
-#endif /* AD_VERSION == AD_VERSION2 */
-        ) {
+       /* Read the adouble header in and parse it.*/
+       if (ad->ad_ops->ad_header_read( ad , pst) < 0
+               || ad->ad_ops->ad_header_upgrade(ad, ad_p) < 0) 
+       {
             int err = errno;
             
             ad_close( ad, adflags );
@@ -1222,6 +1468,68 @@ int ad_open( path, adflags, oflags, mode, ad )
            return -1;
        }
     }
+
+    /* ****************************************** */
+    /* open the resource fork if SFM */
+sfm:
+    if (ad->ad_flags != AD_VERSION1_SFM) {
+       return 0;
+    }
+
+    if ((adflags & ADFLAGS_DIR)) {
+       /* no resource fork for directories / volumes XXX it's false! */
+       return 0;
+    }
+
+    /* untrue yet but ad_close will decremente it*/
+    ad->ad_resource_fork.adf_refcount++;
+
+    if (ad_reso_fileno(ad) != -1) { /* the file is already open */
+        if ((oflags & ( O_RDWR | O_WRONLY)) &&             
+               !(ad->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) {
+
+            ad_close( ad, open_df | ADFLAGS_HF);
+            errno = EACCES;
+           return -1;
+       }
+       return 0;
+    }
+
+    ad_p = ad->ad_ops->ad_path( path, ADFLAGS_RF );
+
+    hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
+    ad->ad_resource_fork.adf_fd = open( ad_p, hoflags, admode );
+    admode = mode;
+    st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
+    
+    if ((ad->ad_options & ADVOL_UNIXPRIV)) {
+       admode = mode;
+    }
+     
+    if (ad->ad_resource_fork.adf_fd < 0 ) {
+       if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
+          hoflags = oflags;
+          ad->ad_resource_fork.adf_fd =open( ad_p, hoflags, admode );
+       }
+    }
+
+    if ( ad->ad_resource_fork.adf_fd < 0) {
+       int err = errno;
+            
+       ad_close( ad, adflags );
+       errno = err;
+       return -1;
+    }
+                        
+    AD_SET(ad->ad_resource_fork.adf_off);
+    ad->ad_resource_fork.adf_flags = hoflags;
+    if ((oflags & O_CREAT) && !st_invalid) {
+        /* just created, set owner if admin (root) */
+        ad_chown(ad_p, &st_dir);
+    }
+    else if (!fstat(ad->ad_resource_fork.adf_fd, &st_meta)) {
+        ad->ad_rlen = st_meta.st_size;
+    }
     return 0 ;
 }
 
@@ -1232,8 +1540,9 @@ int ad_metadata(const char *name, int flags, struct adouble *adp)
 {
     uid_t uid;
     int   ret, err;
+    int   dir = flags & ADFLAGS_DIR;
 
-    if ((ret = ad_open(name, ADFLAGS_HF | flags, O_RDONLY, 0, adp)) < 0 && errno == EACCES) {
+    if ((ret = ad_open(name, ADFLAGS_HF | dir, O_RDONLY, 0, adp)) < 0 && errno == EACCES) {
         uid = geteuid();
         if (seteuid(0)) {
             LOG(log_error, logtype_default, "ad_metadata(%s): seteuid failed %s", name, strerror(errno));
@@ -1241,7 +1550,7 @@ int ad_metadata(const char *name, int flags, struct adouble *adp)
             return -1;
         }
         /* we are root open read only */
-        ret = ad_open(name, ADFLAGS_HF|ADFLAGS_RDONLY|flags, O_RDONLY, 0, adp);
+        ret = ad_open(name, ADFLAGS_HF|ADFLAGS_RDONLY| dir, O_RDONLY, 0, adp);
         err = errno;
         if ( seteuid(uid) < 0) {
             LOG(log_error, logtype_default, "ad_metadata: can't seteuid back");
@@ -1249,6 +1558,28 @@ int ad_metadata(const char *name, int flags, struct adouble *adp)
         }
         errno = err;
     }
+
+    if (!ret && (ADFLAGS_OPENFORKS & flags)) {
+        u_int16_t attrbits = adp->ad_open_forks;
+
+       /* 
+          we need to check if the file is open by another process.
+          it's slow so we only do it if we have to:
+          - it's requested.
+          - we don't already have the answer!
+       */
+       
+       if (!(attrbits & ATTRBIT_ROPEN)) {
+           attrbits |= ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_OPEN_RD) > 0? ATTRBIT_ROPEN : 0;
+           attrbits |= ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_OPEN_WR) > 0? ATTRBIT_ROPEN : 0;
+       }
+
+       if (!(attrbits & ATTRBIT_DOPEN)) {
+           attrbits |= ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_OPEN_RD) > 0? ATTRBIT_DOPEN : 0;
+           attrbits |= ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_OPEN_WR) > 0? ATTRBIT_DOPEN : 0;
+       }
+       adp->ad_open_forks = attrbits;
+    }
     return ret;
 }
 
@@ -1273,6 +1604,10 @@ static int new_rfork(const char *path, struct adouble *ad, int adflags)
        eid = entry_order2;
     else if (ad->ad_flags == AD_VERSION2_OSX)
        eid = entry_order_osx;
+    else  if (ad->ad_flags == AD_VERSION1_SFM) {
+       ad->ad_magic = SFM_MAGIC;
+       eid = entry_order_sfm;
+    }
     else
 #endif
        eid = entry_order1;
@@ -1320,8 +1655,8 @@ static int new_rfork(const char *path, struct adouble *ad, int adflags)
 int ad_refresh(struct adouble *ad)
 {
 
-  if (ad->ad_hf.adf_fd < 0)
+  if (ad_meta_fileno(ad) < 0)
     return -1;
 
-  return ad_header_read(ad, NULL);
+  return ad->ad_ops->ad_header_read(ad, NULL);
 }
index 5c3c93334c38d2c7a00bbb2337602ea3f8291527..c5ad96e853ffe4286118b968ca0cb9731a3ec5c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_read.c,v 1.6 2005-04-28 20:49:52 bfernhomberg Exp $
+ * $Id: ad_read.c,v 1.7 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -71,17 +71,17 @@ ssize_t ad_read( ad, eid, off, buf, buflen)
     /* We're either reading the data fork (and thus the data file)
      * or we're reading anything else (and thus the header file). */
     if ( eid == ADEID_DFORK ) {
-        cc = adf_pread(&ad->ad_df, buf, buflen, off);
+        cc = adf_pread(&ad->ad_data_fork, buf, buflen, off);
     } else {
         off_t r_off;
         
-        if ( ad_hfileno( ad ) == -1 ) {
+        if ( ad_reso_fileno( ad ) == -1 ) {
              /* resource fork is not open ( cf etc/afp/fork.c) */
              return 0;
         }
         r_off = ad_getentryoff(ad, eid) + off;
        
-       if (( cc = adf_pread( &ad->ad_hf, buf, buflen, r_off )) < 0 ) {
+       if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 ) {
          return( -1 );
        }
        /*
@@ -91,7 +91,7 @@ ssize_t ad_read( ad, eid, off, buf, buflen)
         * FIXME : always false?
         */
        if (r_off < ad_getentryoff(ad, ADEID_RFORK)) {
-           if ( ad->ad_hf.adf_flags & O_RDWR ) {
+           if ( ad->ad_resource_fork.adf_flags & O_RDWR ) {
              memcpy(buf, ad->ad_data + r_off,
                     MIN(sizeof( ad->ad_data ) - r_off, cc));
            } else {
index bada1c364a9f7c1ebf1f7b4315f9753b59aaa170..b2b29caeae6254fbf5459b2a3d4c47b2d024a7eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_size.c,v 1.6 2005-04-28 20:49:52 bfernhomberg Exp $
+ * $Id: ad_size.c,v 1.7 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -19,7 +19,7 @@ off_t ad_size(const struct adouble *ad, const u_int32_t eid)
   if (eid == ADEID_DFORK) {
     struct stat st;
     
-    if (fstat(ad_dfileno(ad), &st) < 0)
+    if (fstat(ad_data_fileno(ad), &st) < 0)
       return 0;
     return st.st_size;
   }  
index d7bb789a8b23c1531168d9e794de107d829358eb..1331ae047d7e33c19a485b28fd347cc5735037f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_write.c,v 1.8 2005-04-28 20:49:52 bfernhomberg Exp $
+ * $Id: ad_write.c,v 1.9 2006-09-29 09:39:16 didg Exp $
  *
  * Copyright (c) 1990,1995 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -60,23 +60,23 @@ ssize_t ad_write( ad, eid, off, end, buf, buflen )
     
     if ( eid == ADEID_DFORK ) {
        if ( end ) {
-           if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) {
+           if ( fstat( ad_data_fileno(ad), &st ) < 0 ) {
                return( -1 );
            }
            off = st.st_size - off;
        }
-       cc = adf_pwrite(&ad->ad_df, buf, buflen, off);
+       cc = adf_pwrite(&ad->ad_data_fork, buf, buflen, off);
     } else if ( eid == ADEID_RFORK ) {
         off_t    r_off;
 
        if ( end ) {
-           if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) {
+           if ( fstat( ad_data_fileno(ad), &st ) < 0 ) {
                return( -1 );
            }
            off = st.st_size - off -ad_getentryoff(ad, eid);
        }
        r_off = ad_getentryoff(ad, eid) + off;
-       cc = adf_pwrite(&ad->ad_hf, buf, buflen, r_off);
+       cc = adf_pwrite(&ad->ad_resource_fork, buf, buflen, r_off);
 
        /* sync up our internal buffer  FIXME always false? */
        if (r_off < ad_getentryoff(ad, ADEID_RFORK)) {
@@ -155,7 +155,7 @@ int ad_rtruncate( ad, size )
     struct adouble     *ad;
     const off_t        size;
 {
-    if ( sys_ftruncate( ad->ad_hf.adf_fd,
+    if ( sys_ftruncate( ad_reso_fileno(ad),
            size + ad->ad_eid[ ADEID_RFORK ].ade_off ) < 0 ) {
        return -1;
     }
@@ -168,7 +168,7 @@ int ad_dtruncate(ad, size)
     struct adouble     *ad;
     const off_t        size;
 {
-    if (sys_ftruncate(ad->ad_df.adf_fd, size) < 0) {
+    if (sys_ftruncate(ad_data_fileno(ad), size) < 0) {
       return -1;
     }
     return 0;