]> arthur.barton.de Git - netatalk.git/commitdiff
add the DID to AD2, reenumerate if db is out of sync. This should solve some problems...
authorbfernhomberg <bfernhomberg>
Fri, 6 Feb 2004 13:39:51 +0000 (13:39 +0000)
committerbfernhomberg <bfernhomberg>
Fri, 6 Feb 2004 13:39:51 +0000 (13:39 +0000)
etc/afpd/directory.c
etc/afpd/file.c
include/atalk/adouble.h
libatalk/adouble/ad_attr.c
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c

index cbdfcd844ca12a7f747b3904b52be208075cef7c..b6b75d163dc6323bbf17ecb3903a74868ae4620f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.71.2.4.2.6 2004-01-03 22:21:08 didg Exp $
+ * $Id: directory.c,v 1.71.2.4.2.7 2004-02-06 13:39:51 bfernhomberg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -1932,7 +1932,7 @@ setdirparam_done:
             struct stat *st = &path->st;
 
             ad_setid(&ad,(vol->v_flags & AFPVOL_NODEV)?0:st->st_dev, 
-                         st->st_ino,  curdir->d_did, vol->v_stamp);
+                         st->st_ino,  curdir->d_did, curdir->d_parent->d_did, vol->v_stamp);
         }
     
         ad_flush( &ad, ADFLAGS_HF );
@@ -2029,7 +2029,7 @@ int               ibuflen, *rbuflen;
             ad_getentrylen( &ad, ADEID_NAME ));
 
     ad_setid( &ad, (vol->v_flags & AFPVOL_NODEV)?0:s_path->st.st_dev,
-                   s_path->st.st_ino, dir->d_did, vol->v_stamp);
+                   s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
 
     ad_flush( &ad, ADFLAGS_HF );
     ad_close( &ad, ADFLAGS_HF );
index 230e3fe8d4bbb18f93dc703940a9ea78493d455a..ea58409cc3b3a2a7563b284cc5e48024e7fbb478 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.92.2.2.2.10 2004-02-06 02:32:15 didg Exp $
+ * $Id: file.c,v 1.92.2.2.2.11 2004-02-06 13:39:51 bfernhomberg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -181,6 +181,7 @@ 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
@@ -191,13 +192,17 @@ char   stamp[ADEDLEN_PRIVSYN];
             memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t));
             if (sizeof(stamp) == ad_getentrylen(adp,ADEID_PRIVSYN)) {
                 memcpy(stamp, ad_entry(adp, ADEID_PRIVSYN), sizeof(stamp));
-
-                if (   ((vol->v_flags & AFPVOL_NODEV) || dev == st->st_dev)
-                       && ino == st->st_ino && 
-                       !memcmp(vol->v_stamp, stamp, sizeof(stamp)) ) 
-                {
-                    memcpy(&aint, ad_entry(adp, ADEID_DID), sizeof(aint));
-                    return aint;
+                if (sizeof(cnid_t) == ad_getentrylen(adp, ADEID_DID)) {
+                    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)) &&
+                          (sizeof(cnid_t) == ad_getentrylen(adp, ADEID_PRIVID)) ) 
+                    { 
+                        memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
+                        return aint;
+                    } 
                 }
             }
         }
@@ -227,7 +232,7 @@ char   stamp[ADEDLEN_PRIVSYN];
             /* 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, vol->v_stamp);
+            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);
         }
 #endif    
@@ -1613,6 +1618,55 @@ int              ibuflen, *rbuflen;
     return afp_errno;
 }
 
+static int
+reenumerate_id(const struct vol *vol, char *name, cnid_t did)
+{
+    DIR             *dp;
+    struct dirent   *de;
+    int             ret;
+    struct stat     st;
+    cnid_t         aint;
+    struct adouble  ad;
+       
+
+    if (vol->v_cdb != NULL) {
+       return -1;
+    }
+    if (NULL == ( dp = opendir( name)) ) {
+        return -1;
+    }
+    ret = 0;
+    for ( de = readdir( dp ); de != NULL; de = readdir( dp )) {
+        if (NULL == check_dirent(vol, de->d_name))
+            continue;
+
+        if ( stat(de->d_name, &st)<0 )
+            continue;
+       
+       /* update or add to cnid */
+        aint = cnid_add(vol->v_cdb, &st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */
+
+#if AD_VERSION > AD_VERSION1
+        if (aint != CNID_INVALID && !S_ISDIR(st.st_mode)) {
+            ad_init(&ad, 0);  /* OK */
+            if ( ad_open( de->d_name, ADFLAGS_HF, O_RDWR, 0, &ad ) < 0 ) {
+                continue;
+            }
+            else {
+                ad_setid(&ad,(vol->v_flags & AFPVOL_NODEV)?0:st.st_dev, st.st_ino, aint, did, vol->v_stamp);
+                ad_flush(&ad, ADFLAGS_HF);
+                ad_close(&ad, ADFLAGS_HF);
+           }
+        }
+#endif /* AD_VERSION > AD_VERSION1 */
+
+        ret++;
+    }
+    closedir(dp);
+    return ret;
+}
+
+    
 /* ------------------------------
    resolve a file id */
 int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
@@ -1624,7 +1678,7 @@ int               ibuflen, *rbuflen;
     struct dir         *dir;
     char               *upath;
     struct path         path;
-    int                 err, buflen;
+    int                 err, buflen, retry=0;
     cnid_t             id, cnid;
     u_int16_t          vid, bitmap;
 
@@ -1653,6 +1707,7 @@ int               ibuflen, *rbuflen;
     ibuf += sizeof(id);
     cnid = id;
 
+retry:
     if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
         return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
     }
@@ -1661,7 +1716,26 @@ int              ibuflen, *rbuflen;
         return AFPERR_NOID; /* idem AFPERR_PARAM */
     }
     path.u_name = upath;
-    if (movecwd(vol, dir) < 0 || of_stat(&path) < 0) {
+    if (movecwd(vol, dir) < 0) {
+        switch (errno) {
+        case EACCES:
+        case EPERM:
+            return AFPERR_ACCESS;
+        case ENOENT:
+            return AFPERR_NOID;
+        default:
+            return AFPERR_PARAM;
+        }
+    }
+
+    if ( of_stat(&path) < 0 ) {
+       if ( errno == ENOENT && !retry) {
+           /* cnid db is out of sync, reenumerate the directory and updated ids */
+           reenumerate_id(vol, ".", id);
+           id = cnid;
+           retry = 1;
+           goto retry;
+        }
         switch (errno) {
         case EACCES:
         case EPERM:
@@ -1672,6 +1746,7 @@ int               ibuflen, *rbuflen;
             return AFPERR_PARAM;
         }
     }
+
     /* directories are bad */
     if (S_ISDIR(path.st.st_mode))
         return AFPERR_BADTYPE;
index fe77062175f156f7c4da51c1e33f530929aac897..596ce9608e2c29b61c3f97744df24d8243c2a4aa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.21.6.6 2004-01-31 14:26:24 bfernhomberg Exp $
+ * $Id: adouble.h,v 1.21.6.7 2004-02-06 13:39:52 bfernhomberg Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
 #define ADEID_PRIVDEV           16
 #define ADEID_PRIVINO           17
 #define ADEID_PRIVSYN           18 /* in synch with database */
+#define ADEID_PRIVID            19
 
 #define AD_DEV                  0x80444556
 #define AD_INO                  0x80494E4F
 #define AD_SYN                  0x8053594E
-#define ADEID_MAX              19
+#define AD_ID                   0x8053567E
+#define ADEID_MAX              20
 #endif
 
 /* magic */
 #define ADEDLEN_PRIVDEV         8
 #define ADEDLEN_PRIVINO         8
 #define ADEDLEN_PRIVSYN         8
+#define ADEDLEN_PRIVID          4
 
 #define ADEID_NUM_V1         5
-#define ADEID_NUM_V2         12
+#define ADEID_NUM_V2         13
 
 /* 589 */
 #define AD_DATASZ1      (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT +ADEDLEN_FILEI +ADEDLEN_FINDERI+\
@@ -156,12 +159,12 @@ ADEID_NUM_V1*AD_ENTRY_LEN)
 #endif
 
 #define AD_NEWSZ2       (ADEDLEN_DID + ADEDLEN_AFPFILEI +ADEDLEN_SHORTNAME +ADEDLEN_PRODOSFILEI \
-+ADEDLEN_PRIVDEV +ADEDLEN_PRIVINO +ADEDLEN_PRIVSYN)
++ADEDLEN_PRIVDEV +ADEDLEN_PRIVINO +ADEDLEN_PRIVSYN+ ADEDLEN_PRIVID)
 
 /* 725 */
 #define AD_DATASZ2      (AD_DATASZ1 + AD_NEWSZ2 + (ADEID_NUM_V2 -ADEID_NUM_V1)*AD_ENTRY_LEN)
 
-#if AD_DATASZ2 != 725
+#if AD_DATASZ2 != 741
 #error bad size for AD_DATASZ2
 #endif
 
@@ -417,7 +420,7 @@ extern int ad_setattr __P((const struct adouble *, const u_int16_t));
 extern int ad_getattr __P((const struct adouble *, u_int16_t *));
 
 #if AD_VERSION == AD_VERSION2
-extern int ad_setid __P((struct adouble *, const dev_t dev,const ino_t ino, const u_int32_t, const void *));
+extern int ad_setid __P((struct adouble *, const dev_t dev,const ino_t ino, const u_int32_t, const u_int32_t, const void *));
 #else
 #define ad_setid(a, b, c)
 #endif
index 77c734927c760d0051218ccea43c0aa8521b06f1..49c8ff8e21bdcf44d667bbe9f174d83bf5fe0372 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_attr.c,v 1.4.8.2 2004-01-03 22:21:09 didg Exp $
+ * $Id: ad_attr.c,v 1.4.8.3 2004-02-06 13:39:52 bfernhomberg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -48,7 +48,7 @@ int ad_setattr(const struct adouble *ad, const u_int16_t attr)
  * save file/folder ID in AppleDoubleV2 netatalk private parameters
 */
 #if AD_VERSION == AD_VERSION2
-int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const u_int32_t id, const void *stamp)
+int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const u_int32_t id, const cnid_t did, const void *stamp)
 {
     if (adp->ad_flags == AD_VERSION2 && sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO) 
     {
@@ -58,8 +58,11 @@ int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const u_in
         ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t));
         memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t));
 
-        ad_setentrylen( adp, ADEID_DID, sizeof(id));
-        memcpy(ad_entry( adp, ADEID_DID ), &id, sizeof(id));
+       ad_setentrylen( adp, ADEID_PRIVID, sizeof(id));
+        memcpy(ad_entry( adp, ADEID_PRIVID ), &id, sizeof(id));
+
+        ad_setentrylen( adp, ADEID_DID, sizeof(did));
+        memcpy(ad_entry( adp, ADEID_DID ), &did, sizeof(did));
 
         ad_setentrylen( adp, ADEID_PRIVSYN, ADEDLEN_PRIVSYN);
         memcpy(ad_entry( adp, ADEID_PRIVSYN ), stamp, ADEDLEN_PRIVSYN);
index 87006a8f601988e11e138f55ef95c56c4fa405b9..ce59515216cf056b00fa7268e4da7f0cab3aa38c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_flush.c,v 1.6.6.1 2003-09-09 16:42:21 didg Exp $
+ * $Id: ad_flush.c,v 1.6.6.2 2004-02-06 13:39:52 bfernhomberg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -44,7 +44,7 @@
 static const u_int32_t set_eid[] = {
 0,1,2,3,4,5,6,7,8,
 9,10,11,12,13,14,15,
-AD_DEV, AD_INO, AD_SYN
+AD_DEV, AD_INO, AD_SYN, AD_ID
 };
 
 #define EID_DISK(a) (set_eid[a])
index 6fbccb11ce929c3884a0cafad9747060ba22281d..5fd833d1205e73f6e279f9ae171c307e7d064877 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.30.6.5 2004-01-03 22:16:32 didg Exp $
+ * $Id: ad_open.c,v 1.30.6.6 2004-02-06 13:39:52 bfernhomberg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
 #define ADEDOFF_PRIVDEV      (ADEDOFF_PRODOSFILEI + ADEDLEN_PRODOSFILEI)
 #define ADEDOFF_PRIVINO      (ADEDOFF_PRIVDEV + ADEDLEN_PRIVDEV)
 #define ADEDOFF_PRIVSYN      (ADEDOFF_PRIVINO + ADEDLEN_PRIVINO)
+#define ADEDOFF_PRIVID       (ADEDOFF_PRIVSYN + ADEDLEN_PRIVSYN)
 
-#define ADEDOFF_RFORK_V2     (ADEDOFF_PRIVSYN + ADEDLEN_PRIVSYN)
+#define ADEDOFF_RFORK_V2     (ADEDOFF_PRIVID + ADEDLEN_PRIVID)
 
 /* we keep local copies of a bunch of stuff so that we can initialize things 
  * correctly. */
@@ -176,6 +177,8 @@ static u_int32_t get_eid(struct adouble *ad, u_int32_t eid)
         return ADEID_PRIVINO;
     if (eid == AD_SYN)
         return ADEID_PRIVSYN;
+    if (eid == AD_ID)
+        return ADEID_PRIVID;
 
     return 0;
 }
@@ -194,6 +197,7 @@ static const struct entry entry_order2[ADEID_NUM_V2 +1] = {
   {ADEID_PRIVDEV,     ADEDOFF_PRIVDEV, ADEDLEN_INIT},
   {ADEID_PRIVINO,     ADEDOFF_PRIVINO, ADEDLEN_INIT},
   {ADEID_PRIVSYN,     ADEDOFF_PRIVSYN, ADEDLEN_INIT},
+  {ADEID_PRIVID,     ADEDOFF_PRIVID, ADEDLEN_INIT},
   {ADEID_RFORK, ADEDOFF_RFORK_V2, ADEDLEN_INIT},
 
   {0, 0, 0}
@@ -202,6 +206,111 @@ static const struct entry entry_order2[ADEID_NUM_V2 +1] = {
 
 #if AD_VERSION == AD_VERSION2
 
+static int ad_update(struct adouble *ad, const char *path)
+{
+  struct stat st;
+  u_int16_t nentries = 0;
+  off_t     off, shiftdata=0;
+  const struct entry  *eid;
+  static off_t entry_len[ADEID_MAX];
+  static char  databuf[ADEID_MAX][256], *buf;
+  int fd;
+
+  /* check to see if we should convert this header. */
+  if (!path || (ad->ad_version != AD_VERSION2))
+    return 0;
+  
+  if (ad->ad_eid[ADEID_RFORK].ade_off)  
+    shiftdata = ADEDOFF_RFORK_V2 -ad->ad_eid[ADEID_RFORK].ade_off;
+
+  memcpy(&nentries, ad->ad_data + ADEDOFF_NENTRIES, sizeof( nentries ));
+  nentries = ntohs( nentries );
+
+  if ( shiftdata == 0 && nentries == ADEID_NUM_V2)
+    return 0;
+
+  memset(entry_len, 0, sizeof(entry_len));
+  memset(databuf, 0, sizeof(databuf));
+
+  /* bail if we can't get a lock */
+  if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0, 0) < 0)
+    goto bail_err;
+
+  if ((fd = open(path, O_RDWR)) < 0)
+    goto bail_lock;
+
+  if (fstat(fd, &st) ||
+    sys_ftruncate(fd, st.st_size + shiftdata) < 0) {
+    goto bail_open;
+  }
+  if (st.st_size > 0x7fffffff) {
+    LOG(log_debug, logtype_default, "ad_update: file '%s' too big for update.", path);
+    goto bail_truncate;
+  }
+  /* last place for failure. */
+  if ((void *) (buf = (char *)
+                mmap(NULL, st.st_size + shiftdata,
+                     PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
+          MAP_FAILED) {
+    goto bail_truncate;
+  }
+
+  off = ad->ad_eid[ADEID_RFORK].ade_off;
+
+  /* move the RFORK. this assumes that the RFORK is at the end */
+  if (off) {
+    memmove(buf + ADEDOFF_RFORK_V2, buf + off, ad->ad_eid[ADEID_RFORK].ade_len);
+  }
+
+  munmap(buf, st.st_size + shiftdata);
+  close(fd);
+
+  /* now, fix up our copy of the header */
+  memset(ad->ad_filler, 0, sizeof(ad->ad_filler));
+  /* save the header entries */ 
+  eid = entry_order2;
+  while (eid->id) {
+    if( ad->ad_eid[eid->id].ade_off != 0) {
+      if ( eid->id > 2 && ad->ad_eid[eid->id].ade_len < 256)
+        memcpy( databuf[eid->id], ad->ad_data +ad->ad_eid[eid->id].ade_off, ad->ad_eid[eid->id].ade_len);
+      entry_len[eid->id] = ad->ad_eid[eid->id].ade_len;
+    }
+    eid++;
+  }
+
+  memset(ad->ad_data + AD_HEADER_LEN, 0, AD_DATASZ - AD_HEADER_LEN);
+
+  /* copy the saved entries to the new header */
+  eid = entry_order2;
+  while (eid->id) {
+    if ( eid->id > 2 && entry_len[eid->id] > 0) {
+      memcpy(ad->ad_data+eid->offset, databuf[eid->id], entry_len[eid->id]);
+    }
+    ad->ad_eid[eid->id].ade_off = eid->offset;
+    ad->ad_eid[eid->id].ade_len = entry_len[eid->id];
+    eid++;
+  }
+
+  /* rebuild the header and cleanup */
+  ad_flush(ad, ADFLAGS_HF );
+  ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
+
+  LOG(log_debug, logtype_default, "updated AD2 header %s", path);
+
+  return 0;
+
+bail_truncate:
+  sys_ftruncate(fd, st.st_size);
+bail_open:
+  close(fd);
+bail_lock:
+  ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
+bail_err:
+  return -1;
+}
+
+
 /* FIXME work only if < 2GB */
 static int ad_v1tov2(struct adouble *ad, const char *path)
 {
@@ -302,6 +411,8 @@ static int ad_v1tov2(struct adouble *ad, const char *path)
   ad->ad_eid[ADEID_PRIVINO].ade_len = ADEDLEN_INIT;
   ad->ad_eid[ADEID_PRIVSYN].ade_off = ADEDOFF_PRIVSYN;
   ad->ad_eid[ADEID_PRIVSYN].ade_len = ADEDLEN_INIT;
+  ad->ad_eid[ADEID_PRIVID].ade_off  = ADEDOFF_PRIVID;
+  ad->ad_eid[ADEID_PRIVID].ade_len =  ADEDLEN_INIT;
   
   /* shift the old entries (NAME, COMMENT, FINDERI, RFORK) */
   ad->ad_eid[ADEID_NAME].ade_off = ADEDOFF_NAME_V2;
@@ -912,7 +1023,7 @@ int ad_open( path, adflags, oflags, mode, ad )
            /* Read the adouble header in and parse it.*/
        if ((ad_header_read( ad , &st) < 0)
 #if AD_VERSION == AD_VERSION2
-               || (ad_v1tov2(ad, ad_p) < 0)
+               || (ad_v1tov2(ad, ad_p) < 0) || (ad_update(ad, ad_p) < 0)
 #endif /* AD_VERSION == AD_VERSION2 */
         ) {
             ad_close( ad, adflags );