]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/file.c
Merge symlink branch
[netatalk.git] / etc / afpd / file.c
index 84caef4d22acd5be432f6b7944fd337256bccfc0..915219f595d11d7ea53876adc269a26a8b484b0b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.121 2009-11-08 23:17:39 didg Exp $
+ * $Id: file.c,v 1.134 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -89,7 +89,7 @@ static int default_type(void *finder)
 }
 
 /* FIXME path : unix or mac name ? (for now it's unix name ) */
-void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data)
+void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data, int islink)
 {
     struct extmap      *em;
     void                *ad_finder = NULL;
@@ -114,6 +114,17 @@ void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *a
             memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
         }
     }
+
+    if (islink){
+        u_int16_t linkflag;
+        memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
+        linkflag |= htons(FINDERINFO_ISALIAS);
+        memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2);
+        memcpy((char *)data + FINDERINFO_FRTYPEOFF,"slnk",4); 
+        memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4); 
+        chk_ext = 0;
+    }
+
     /** Only enter if no appledouble information and no finder information found. */
     if (chk_ext && (em = getextmap( upath ))) {
         memcpy(data, em->em_type, sizeof( em->em_type ));
@@ -187,25 +198,24 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t
                                  (1 << FILPBIT_RFLEN) |\
                                  (1 << FILPBIT_EXTRFLEN) |\
                                  (1 << FILPBIT_PDINFO) |\
+                                 (1 << FILPBIT_FNUM) |\
                                  (1 << FILPBIT_UNIXPR)))
 
 /* -------------------------- */
 u_int32_t get_id(struct vol *vol, struct adouble *adp,  const struct stat *st,
-             const cnid_t did, char *upath, const int len) 
+                 const cnid_t did, char *upath, const int len) 
 {
-u_int32_t aint = 0;
-
-#if AD_VERSION > AD_VERSION1
-
-    if ((aint = ad_getid(adp, st->st_dev, st->st_ino, did, vol->v_stamp))) {
-       return aint;
-    }
-#endif
+    u_int32_t adcnid;
+    u_int32_t dbcnid = CNID_INVALID;
 
     if (vol->v_cdb != NULL) {
-           aint = cnid_add(vol->v_cdb, st, did, upath, len, aint);
+        /* prime aint with what we think is the cnid, set did to zero for
+           catching moved files */
+        adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp);
+
+           dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid);
            /* Throw errors if cnid_add fails. */
-           if (aint == CNID_INVALID) {
+           if (dbcnid == CNID_INVALID) {
             switch (errno) {
             case CNID_ERR_CLOSE: /* the db is closed */
                 break;
@@ -221,18 +231,15 @@ u_int32_t aint = 0;
                 return CNID_INVALID;
             }
         }
-#if AD_VERSION > AD_VERSION1
-        else if (adp ) {
-            /* update the ressource fork
-             * for a folder adp is always null
-             */
-            if (ad_setid(adp, st->st_dev, st->st_ino, aint, did, vol->v_stamp)) {
+        else if (adp && (adcnid != dbcnid)) {
+            /* Update the ressource fork. For a folder adp is always null */
+            LOG(log_debug, logtype_afpd, "get_id: calling ad_setid. adcnid: %u, dbcnid: %u", htonl(adcnid), htonl(dbcnid));
+            if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) {
                 ad_flush(adp);
             }
         }
-#endif    
     }
-    return aint;
+    return dbcnid;
 }
              
 /* -------------------------- */
@@ -268,7 +275,7 @@ int getmetadata(struct vol *vol,
             id = get_id(vol, adp, st, dir->d_did, upath, strlen(upath));
         else 
             id = path->id;
-        if (id == 0)
+        if (id == CNID_INVALID)
             return afp_errno;
         if (!path->m_name) {
             path->m_name = utompath(vol, upath, id, utf8_encoding());
@@ -336,7 +343,7 @@ int getmetadata(struct vol *vol,
             break;
 
         case FILPBIT_FINFO :
-           get_finderinfo(vol, upath, adp, (char *)data);
+               get_finderinfo(vol, upath, adp, (char *)data,S_ISLNK(st->st_mode));
             data += ADEDLEN_FINDERI;
             break;
 
@@ -531,7 +538,7 @@ int getfilparams(struct vol *vol,
         adp = of_ad(vol, path, &ad);
         upath = path->u_name;
 
-        if ( ad_metadata( upath, flags, adp) < 0 ) {
+        if ( ad_metadata( upath, flags|ADFLAGS_CREATE, adp) < 0 ) {
             switch (errno) {
             case EACCES:
                 LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
@@ -623,7 +630,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
         openf = O_RDWR|O_CREAT|O_EXCL;
     }
 
-    if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
+    if ( ad_open( upath, ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
                   openf, 0666, adp) < 0 ) {
         switch ( errno ) {
         case EROFS:
@@ -741,7 +748,7 @@ int setfilparams(struct vol *vol,
     int                        bit, isad = 1, err = AFP_OK;
     char                *upath;
     u_char              achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
-    u_int16_t          ashort, bshort;
+    u_int16_t          ashort, bshort, oshort;
     u_int32_t          aint;
     u_int32_t          upriv;
     u_int16_t           upriv_bit = 0;
@@ -799,6 +806,27 @@ int setfilparams(struct vol *vol,
         case FILPBIT_FINFO :
             change_mdate = 1;
             memcpy(finder_buf, buf, 32 );
+            if (memcmp(buf,"slnkrhap",8)==0 && !S_ISLNK(path->st.st_mode)){
+            // SLFINFO
+                int fp;
+                ssize_t len;
+                int erc=1;
+                char buf[PATH_MAX+1];
+                if ((fp=open(path->u_name,O_RDONLY))>=0){
+                    if (len=read(fp,buf,PATH_MAX+1)){
+                        if (unlink(path->u_name)==0){
+                            buf[len]=0;
+                            erc=symlink(buf,path->u_name);  
+                            lstat(path->u_name,&(path->st));
+                        }
+                    }
+                    close(fp);
+                }
+                if (erc!=0){
+                    err=AFPERR_BITMAP;
+                    goto setfilparam_done;
+                }
+            }
             buf += 32;
             break;
         case FILPBIT_UNIXPR :
@@ -861,7 +889,7 @@ int setfilparams(struct vol *vol,
 
     /* second try with adouble open 
     */
-    if ( ad_open_metadata( upath, vol_noadouble(vol), O_CREAT, adp) < 0) {
+    if ( ad_open_metadata( upath, 0, O_CREAT, adp) < 0) {
         LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error");
         /*
          * For some things, we don't need an adouble header:
@@ -889,14 +917,14 @@ int setfilparams(struct vol *vol,
         switch(  bit ) {
         case FILPBIT_ATTR :
             ad_getattr(adp, &bshort);
-            if ((bshort & htons(ATTRBIT_INVISIBLE)) !=
-                (ashort & htons(ATTRBIT_INVISIBLE) & htons(ATTRBIT_SETCLR)) )
-                change_parent_mdate = 1;
+            oshort = bshort;
             if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
                 bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
             } else {
                 bshort &= ~ashort;
             }
+            if ((bshort & htons(ATTRBIT_INVISIBLE)) != (oshort & htons(ATTRBIT_INVISIBLE)))
+                change_parent_mdate = 1;
             ad_setattr(adp, bshort);
             break;
         case FILPBIT_CDATE :
@@ -1498,7 +1526,11 @@ int deletefile(const struct vol *vol, char *file, int checkAttrib)
     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 ) {
+        /* we never want to create a resource fork here, we are going to delete it 
+         * moreover sometimes deletefile is called with a no existent file and 
+         * ad_open would create a 0 byte resource fork
+        */
+        if ( ad_metadata( file, ADFLAGS_OPENFORKS, &ad) == 0 ) {
             ad_close( &ad, adflags );
             if ((err = check_attrib(&ad))) {
                return err;
@@ -1654,7 +1686,7 @@ static int reenumerate_loop(struct dirent *de, char *mname _U_, void *data)
     cnid_t        did  = param->did;
     cnid_t       aint;
     
-    if ( stat(de->d_name, &path.st)<0 )
+    if ( lstat(de->d_name, &path.st)<0 )
         return 0;
     
     /* update or add to cnid */
@@ -1699,7 +1731,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir)
     }
     
     /* FIXME use of_statdir ? */
-    if (stat(name, &st)) {
+    if (lstat(name, &st)) {
        return -1;
     }
 
@@ -1869,7 +1901,7 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_
     }
 
     err = AFP_OK;
-    if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
+    if ((movecwd(vol, dir) < 0) || (lstat(upath, &st) < 0)) {
         switch (errno) {
         case EACCES:
         case EPERM:
@@ -2114,10 +2146,10 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
     if (did) {
        cnid_delete(vol->v_cdb, did);
     }
-    if ((did && ( (crossdev && stat( upath, &srcst) < 0) || 
+    if ((did && ( (crossdev && lstat( upath, &srcst) < 0) || 
                 cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0))
        ||
-       (sid && ( (crossdev && stat(p, &destst) < 0) ||
+       (sid && ( (crossdev && lstat(p, &destst) < 0) ||
                 cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0))
     ) {
         switch (errno) {