]> arthur.barton.de Git - netatalk.git/commitdiff
Merge symlink branch HEAD-after-symlink-merge
authorfranklahm <franklahm>
Wed, 10 Feb 2010 14:05:36 +0000 (14:05 +0000)
committerfranklahm <franklahm>
Wed, 10 Feb 2010 14:05:36 +0000 (14:05 +0000)
19 files changed:
NEWS
configure.in
etc/afpd/acls.c
etc/afpd/afp_asp.c
etc/afpd/catsearch.c
etc/afpd/directory.c
etc/afpd/enumerate.c
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/filedir.c
etc/afpd/ofork.c
etc/afpd/quota.c
etc/afpd/unix.c
include/atalk/adouble.h
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c
libatalk/adouble/ad_read.c
libatalk/vfs/ea.c
libatalk/vfs/unix.c

diff --git a/NEWS b/NEWS
index 5441053468672a8eaa50ab6b1f0dd2f4870b42ed..eb3b86de7eec770df9dfe4256abb33da57a05756 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,7 @@ Changes in 2.1-beta1
 
 * NEW: afpd: AFP 3.2 support
 * NEW: afpd: Extended Attributes support using native attributes or
-             using files inside .AppleDouble directories.
+       using files inside .AppleDouble directories.
 * NEW: afpd: ACL support with ZFS
 * NEW: cnid_metad: options -l and -f to configure logging
 * NEW: IPv6 support
@@ -20,7 +20,7 @@ Changes in 2.1-beta1
 * NEW: configure args to download and install a "private" Webmin instance
        including only basic Webmin modules plus our netatalk.wbm.
 * NEW: fallback to a temporary in memory tdb CNID database if the volume
-       database can't be open.
+       database can't be opened.
 * NEW: support for Unicode characters in the range above U+010000 using
        internal surrogate pairs
 * NEW: apple_dump: utility to dump AppleSingle and AppleDouble files
@@ -29,6 +29,8 @@ Changes in 2.1-beta1
        SRVLOC is legacy.
 * UPD: cdb/dbd CNID backend requires BerkeleyDB >= 4.6
 * UPD: afpd: try to install PAM config that pulls in system|common auth
+* UPD: afpd: symlink handling: never followed server side, client resolves
+       them, so it's safe to use them now.
 * FIX: rewritten logger
 * FIX: afpd: UNIX permissions handling
 * FIX: cnid_dbd: always use BerkeleyDB transactions
@@ -40,8 +42,8 @@ Changes in 2.1-beta1
        which is in our case the last configured one. atalkd now tries to
        find the right one.
        Note: now a misconfigured or plugged router can broadcast a wrong route !
-* REM: cnid_maint: use dbd [FIXME: s/dbd/INSERT NAME HERE/]
-* REM: cleanappledouble.pl: use dbd [FIXME: s/dbd/INSERT NAME HERE/]
+* REM: cnid_maint: use dbd
+* REM: cleanappledouble.pl: use dbd
 * REM: nu: use `macusers` instead
 
 Changes in 2.0.5
index eaa9488fc0833d73ceb2e4507e5ea33dd05781df..1c107098d246ef6e5d13af149acacc9ad06916ca 100644 (file)
@@ -1,4 +1,4 @@
-dnl $Id: configure.in,v 1.237 2010-01-26 18:13:48 franklahm Exp $
+dnl $Id: configure.in,v 1.238 2010-02-10 14:05:36 franklahm Exp $
 dnl configure.in for netatalk
 
 AC_INIT(etc/afpd/main.c)
@@ -1152,6 +1152,35 @@ if test "x$neta_cv_eas_sys_found" = "xyes" ; then
    fi
 fi
 
+dnl --------------------- Check if realpath() takes NULL
+AC_CACHE_CHECK([if the realpath function allows a NULL argument],
+    neta_cv_REALPATH_TAKES_NULL, [
+        AC_TRY_RUN([
+            #include <stdio.h>
+            #include <limits.h>
+            #include <signal.h>
+
+            void exit_on_core(int ignored) {
+                 exit(1);
+            }
+
+            main() {
+                char *newpath;
+                signal(SIGSEGV, exit_on_core);
+                newpath = realpath("/tmp", NULL);
+                exit((newpath != NULL) ? 0 : 1);
+            }],
+            neta_cv_REALPATH_TAKES_NULL=yes,
+            neta_cv_REALPATH_TAKES_NULL=no,
+            neta_cv_REALPATH_TAKES_NULL=cross
+        )
+    ]
+)
+
+if test x"$neta_cv_REALPATH_TAKES_NULL" = x"yes"; then
+    AC_DEFINE(REALPATH_TAKES_NULL,1,[Whether the realpath function allows NULL])
+fi
+
 dnl --------------------- Netatalk Webmin
 NETATALK_WEBMIN
 
index a3d17f3fef07156cce44f1c47f3bc3e20822d9ca..f5d3eaab1bebf841d01caefef0ef823b29ea4513 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: acls.c,v 1.7 2009-11-28 13:06:30 franklahm Exp $
+  $Id: acls.c,v 1.8 2010-02-10 14:05:37 franklahm Exp $
   Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -583,7 +583,7 @@ static int check_acl_access(const char *path, const uuidp_t uuid, uint32_t reque
     }
 
     /* File or dir */
-    if ((stat(path, &st)) != 0) {
+    if ((lstat(path, &st)) != 0) {
         LOG(log_error, logtype_afpd, "check_access: stat: %s", strerror(errno));
         ret = AFPERR_PARAM;
         goto exit;
index dddb3da5030032b4d68cc3265ee0b306da58da66..ea40e58f8a9e45b027fe52a14a5f4101dbfcf2be 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_asp.c,v 1.27 2009-10-25 07:18:11 didg Exp $
+ * $Id: afp_asp.c,v 1.28 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -81,7 +81,7 @@ static void afp_authprint_remove(AFPObj *obj)
 
     memset( addr_filename_buff, 0, 256 );
 
-    if(stat(addr_filename, &cap_st) == 0) {
+    if(lstat(addr_filename, &cap_st) == 0) {
        if( S_ISREG(cap_st.st_mode) ) {
            int len;
            int capfd = open( addr_filename, O_RDONLY );
index ccbdd80fbcb7b82671422e7c3c7201f7a02d215a..46192e35465bf9de01e3030fac1c045893ef37b8 100644 (file)
@@ -237,13 +237,13 @@ static struct finderinfo *unpack_buffer(struct finderinfo *finfo, char *buffer)
 
 /* -------------------- */
 static struct finderinfo *
-unpack_finderinfo(struct vol *vol, struct path *path, struct adouble **adp, struct finderinfo *finfo)
+unpack_finderinfo(struct vol *vol, struct path *path, struct adouble **adp, struct finderinfo *finfo, int islnk)
 {
        packed_finder  buf;
        void           *ptr;
        
     *adp = adl_lkup(vol, path, *adp);
-       ptr = get_finderinfo(vol, path->u_name, *adp, &buf);
+       ptr = get_finderinfo(vol, path->u_name, *adp, &buf,islnk);
        return unpack_buffer(finfo, ptr);
 }
 
@@ -265,6 +265,8 @@ static int crit_check(struct vol *vol, struct path *path) {
        u_int32_t ac_date, ab_date;
        static char convbuf[514]; /* for convert_charset dest_len parameter +2 */
        size_t len;
+    int islnk;
+    islnk=S_ISLNK(path->st.st_mode);
 
        if (S_ISDIR(path->st.st_mode)) {
                if (!c1.dbitmap)
@@ -379,7 +381,7 @@ static int crit_check(struct vol *vol, struct path *path) {
 
         /* Check file type ID */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.f_type != 0) {
-           finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+           finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                if (finfo->f_type != c1.finfo.f_type)
                        goto crit_check_ret;
        }
@@ -387,7 +389,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        /* Check creator ID */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.creator != 0) {
                if (!finfo) {
-                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
                if (finfo->creator != c1.finfo.creator)
                        goto crit_check_ret;
@@ -396,7 +398,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        /* Check finder info attributes */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.attrs != 0) {
                if (!finfo) {
-                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
 
                if ((finfo->attrs & c2.finfo.attrs) != c1.finfo.attrs)
@@ -406,7 +408,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        /* Check label */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.label != 0) {
                if (!finfo) {
-                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
                if ((finfo->label & c2.finfo.label) != c1.finfo.label)
                        goto crit_check_ret;
index 11c6de7ea47142af52964e5d7e6778d0d5a5402e..f330d3ca910fa77c9260eb7898dfd0bc2d2019e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.131 2010-01-26 20:39:52 didg Exp $
+ * $Id: directory.c,v 1.132 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -133,6 +133,76 @@ static struct dir rootpar  = { SENTINEL, SENTINEL, NULL,
  * frPutAway:   4    home directory ID
  */
 
+/*!
+ * @brief symlink safe chdir replacement
+ *
+ * Only chdirs to dir if it doesn't contain symlinks.
+ *
+ * @returns 1 if a path element is a symlink, 0 otherwise, -1 on syserror
+ */
+static int lchdir(const char *dir)
+{
+    int ret = 0;
+    char buf[MAXPATHLEN+1];
+#ifdef REALPATH_TAKES_NULL
+    char *rpath = NULL;
+#else
+    char rpath[MAXPATHLEN+1];
+#endif
+
+    /* dir might be an relative or an absolute path */
+    if (dir[0] == '/') {
+        /* absolute path, just make sure buf is prepared for strlcat */
+        buf[0] = 0;
+    } else {
+        /* relative path, push cwd int buf */
+        if (getcwd(buf, MAXPATHLEN) == NULL)
+            return -1;
+        if (strlcat(buf, "/", MAXPATHLEN) >= MAXPATHLEN)
+            return -1;
+    }
+
+    if (strlcat(buf, dir, MAXPATHLEN) >= MAXPATHLEN)
+        return -1;
+
+#ifdef REALPATH_TAKES_NULL
+    if ((rpath = realpath(dir, NULL)) == NULL) {
+#else
+    if (realpath(dir, rpath) == NULL) {
+#endif
+        ret = -1;
+        goto exit;
+    }
+
+    /* 
+     * Cases:
+     * chdir request   | realpath result | ret
+     * (after getwcwd) |                 |
+     * =======================================
+     * /a/b/.          | /a/b            | 0
+     * /a/b/.          | /c              | 1
+     * /a/b/.          | /c/d/e/f        | 1
+     */
+    ret = 0;
+    for (int i = 0; rpath[i]; i++) {
+        if (buf[i] != rpath[i]) {
+            ret = 1;
+            goto exit;
+        }
+    }
+
+    if (chdir(dir) != 0) {
+        ret = -1;
+        goto exit;
+    }
+
+exit:
+#ifdef REALPATH_TAKES_NULL
+    free(rpath);
+#endif
+    return ret;
+}
+
 static struct dir *
 vol_tree_root(const struct vol *vol, u_int32_t did)
 {
@@ -818,7 +888,7 @@ static int deletedir(char *dir)
             break;
         }
         strcpy(path + len, de->d_name);
-        if (stat(path, &st)) {
+        if (lstat(path, &st)) {
             continue;
         }
         if (S_ISDIR(st.st_mode)) {
@@ -884,7 +954,7 @@ static int copydir(const struct vol *vol, char *src, char *dst)
         }
         strcpy(spath + slen, de->d_name);
 
-        if (stat(spath, &st) == 0) {
+        if (lstat(spath, &st) == 0) {
             if (strlen(de->d_name) > drem) {
                 err = AFPERR_PARAM;
                 break;
@@ -906,7 +976,7 @@ static int copydir(const struct vol *vol, char *src, char *dst)
     }
 
     /* keep the same time stamp. */
-    if (stat(src, &st) == 0) {
+    if (lstat(src, &st) == 0) {
         ut.actime = ut.modtime = st.st_mtime;
         utime(dst, &ut);
     }
@@ -1542,6 +1612,7 @@ int movecwd(struct vol *vol, struct dir *dir)
     struct dir  *d;
     char    *p, *u;
     int     n;
+    int     ret;
 
     if ( dir == curdir ) {
         return( 0 );
@@ -1580,7 +1651,14 @@ int movecwd(struct vol *vol, struct dir *dir)
         p -= n;
         memcpy( p, vol->v_path, n );
     }
-    if ( chdir( p ) < 0 ) {
+    if ( (ret = lchdir( p )) != 0 ) {
+        LOG(log_debug, logtype_afpd, "movecwd('%s'): ret:%d, %u/%s", p, ret, errno, strerror(errno));
+
+        if (ret == 1) {
+            /* p is a symlink */
+            afp_errno = AFPERR_BADTYPE;
+            return -1;
+        }
         switch (errno) {
         case EACCES:
         case EPERM:
index 15235c6f6242b9bec574e50d3d73313df1abf545..c06ef20300f3f296e4e2b0d41b2b40404a4538b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: enumerate.c,v 1.48 2010-01-11 11:09:36 franklahm Exp $
+ * $Id: enumerate.c,v 1.49 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -280,7 +280,7 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
     if ( sindex == 1 || curdir->d_did != sd.sd_did || vid != sd.sd_vid ) {
         sd.sd_last = sd.sd_buf;
         /* if dir was in the cache we don't have the inode */
-        if (( !o_path->st_valid && stat( ".", &o_path->st ) < 0 ) ||
+        if (( !o_path->st_valid && lstat( ".", &o_path->st ) < 0 ) ||
               (ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) 
         {
             switch (errno) {
index 31107ce28177101c76f79efea70483003817d30e..915219f595d11d7ea53876adc269a26a8b484b0b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.133 2010-02-08 10:29:22 franklahm 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 ));
@@ -332,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;
 
@@ -795,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 :
@@ -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) {
index c4253ca07d3849df446e9631407e41eb5c8efbec..9d3ca116177d0145d17cc189b1fb61e77605404f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.24 2009-10-15 10:43:13 didg Exp $
+ * $Id: file.h,v 1.25 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -122,7 +122,7 @@ extern int deletefile   (const struct vol *, char *, int);
 extern int getmetadata  (struct vol *vol, u_int16_t bitmap, struct path *path, 
                          struct dir *dir, char *buf, size_t *buflen, struct adouble *adp);
 
-extern void *get_finderinfo (const struct vol *, const char *, struct adouble *, void *);
+extern void *get_finderinfo (const struct vol *, const char *, struct adouble *, void *, int);
 
 extern size_t mtoUTF8   (const struct vol *, const char *, size_t , char *, size_t );
 extern int  copy_path_name (const struct vol *, char *, char *i);
index 897bb5768c4cf99222ca59449ee9be2425e79454..4451ae804c29ec0a2717ae488e93db7f4ad5d0a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.c,v 1.69 2010-01-21 14:14:49 didg Exp $
+ * $Id: filedir.c,v 1.70 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -98,7 +98,7 @@ more information */
                     upath, strerror(errno));
                 ret = AFPERR_ACCESS;
             }
-            else if (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)
+            else if ((!S_ISLNK(st->st_mode)) && (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0))
             {
                 LOG(log_error, logtype_afpd,
                     "matchfile2dirperms(%s): Error adding file read permissions: %s",
index 9bb6966770effcd6f627ff91746e7990d3f96224..d9c4f31e8e5b0d2685b740a9cddf0dc6a8303fa7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ofork.c,v 1.30 2009-11-13 00:27:36 didg Exp $
+ * $Id: ofork.c,v 1.31 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1996 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -285,7 +285,7 @@ int of_stat  (struct path *path)
 int ret;
     path->st_errno = 0;
     path->st_valid = 1;
-    if ((ret = stat(path->u_name, &path->st)) < 0)
+    if ((ret = lstat(path->u_name, &path->st)) < 0)
        path->st_errno = errno;
    return ret;
 }
@@ -309,7 +309,7 @@ int ret;
     /* FIXME, what about: we don't have r-x perm anymore ? */
     strlcpy(pathname +3, path->d_dir->d_u_name, sizeof (pathname) -3);
 
-    if (!(ret = stat(pathname, &path->st)))
+    if (!(ret = lstat(pathname, &path->st)))
         return 0;
         
     path->st_errno = errno;
@@ -318,7 +318,7 @@ int ret;
        if (movecwd(vol, curdir->d_parent)) 
            return -1;
        path->st_errno = 0;
-       if ((ret = stat(path->d_dir->d_u_name, &path->st)) < 0) 
+       if ((ret = lstat(path->d_dir->d_u_name, &path->st)) < 0) 
            path->st_errno = errno;
     }
     return ret;
index e40de5fab87fb5f16cc1d6a3d02cafa8a7d1774e..26aae15be97f8e9852715d5d0ce8407365bbb190 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: quota.c,v 1.33 2010-01-21 14:14:49 didg Exp $
+ * $Id: quota.c,v 1.34 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -296,7 +296,7 @@ mountp( char *file, int *nfs)
     dev_t                      devno;
     static struct mnttab       mnt;
 
-    if ( stat( file, &sb ) < 0 ) {
+    if ( lstat( file, &sb ) < 0 ) {
         return( NULL );
     }
     devno = sb.st_dev;
@@ -307,14 +307,14 @@ mountp( char *file, int *nfs)
 
     while ( getmntent( mtab, &mnt ) == 0 ) {
         /* local fs */
-        if ( (stat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) {
+        if ( (lstat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) {
             fclose( mtab );
             return mnt.mnt_mountp;
         }
 
         /* check for nfs. we probably should use
          * strcmp(mnt.mnt_fstype, MNTTYPE_NFS), but that's not as fast. */
-        if ((stat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) &&
+        if ((lstat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) &&
                 strchr(mnt.mnt_special, ':')) {
             *nfs = 1;
             fclose( mtab );
@@ -384,7 +384,7 @@ special(char *file, int *nfs)
     struct mntent      *mnt;
     int                found=0;
 
-    if ( stat( file, &sb ) < 0 ) {
+    if ( lstat( file, &sb ) < 0 ) {
         return( NULL );
     }
     devno = sb.st_dev;
@@ -395,14 +395,14 @@ special(char *file, int *nfs)
 
     while (( mnt = getmntent( mtab )) != NULL ) {
         /* check for local fs */
-        if ( (stat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) {
+        if ( (lstat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) {
            found = 1;
            break;
         }
 
         /* check for an nfs mount entry. the alternative is to use
         * strcmp(mnt->mnt_type, MNTTYPE_NFS) instead of the strchr. */
-        if ((stat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) &&
+        if ((lstat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) &&
                 strchr(mnt->mnt_fsname, ':')) {
             *nfs = 1;
            found = 1;
index d5bde724b9190ccb062122299ee879b2491575ec..57491a7184a200f17b48a2e5a1f9d9959e84f958 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.c,v 1.60 2010-01-20 13:22:13 franklahm Exp $
+ * $Id: unix.c,v 1.61 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -178,7 +178,7 @@ struct stat     sb;
 
     ma->ma_user = ma->ma_owner = ma->ma_world = ma->ma_group = 0;
     if (!st) {
-        if (stat(path, &sb) != 0)
+        if (lstat(path, &sb) != 0)
             return;
         st = &sb;
     }
@@ -281,7 +281,7 @@ int setdeskmode(const mode_t mode)
             *m = '\0';
             strcat( modbuf, subp->d_name );
             /* XXX: need to preserve special modes */
-            if (stat(modbuf, &st) < 0) {
+            if (lstat(modbuf, &st) < 0) {
                 LOG(log_error, logtype_afpd, "setdeskmode: stat %s: %s",fullpathname(modbuf), strerror(errno) );
                 continue;
             }
@@ -388,7 +388,7 @@ int setdirmode(const struct vol *vol, const char *name, mode_t mode)
         if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) {
             continue;
         }
-        if ( stat( dirp->d_name, &st ) < 0 ) {
+        if ( lstat( dirp->d_name, &st ) < 0 ) {
             LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s",dirp->d_name, strerror(errno) );
             continue;
         }
@@ -489,7 +489,7 @@ int setfilowner(const struct vol *vol, const uid_t uid, const gid_t gid, struct
         return -1;
     }
 
-    if ( chown( path->u_name, uid, gid ) < 0 && errno != EPERM ) {
+    if ( lchown( path->u_name, uid, gid ) < 0 && errno != EPERM ) {
         LOG(log_debug, logtype_afpd, "setfilowner: chown %d/%d %s: %s",
             uid, gid, path->u_name, strerror(errno) );
        return -1;
@@ -523,13 +523,13 @@ int setdirowner(const struct vol *vol, const char *name, const uid_t uid, const
         if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) {
             continue;
         }
-        if ( stat( dirp->d_name, &st ) < 0 ) {
+        if ( lstat( dirp->d_name, &st ) < 0 ) {
             LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s",
                 fullpathname(dirp->d_name), strerror(errno) );
             continue;
         }
         if (( st.st_mode & S_IFMT ) == S_IFREG ) {
-            if ( chown( dirp->d_name, uid, gid ) < 0 && errno != EPERM ) {
+            if ( lchown( dirp->d_name, uid, gid ) < 0 && errno != EPERM ) {
                 LOG(log_debug, logtype_afpd, "setdirowner: chown %s: %s",
                     fullpathname(dirp->d_name), strerror(errno) );
                 /* return ( -1 ); Sometimes this is okay */
@@ -542,10 +542,10 @@ int setdirowner(const struct vol *vol, const char *name, const uid_t uid, const
         return -1;
     }
     
-    if ( stat( ".", &st ) < 0 ) {
+    if ( lstat( ".", &st ) < 0 ) {
         return( -1 );
     }
-    if ( gid && gid != st.st_gid && chown( ".", uid, gid ) < 0 && errno != EPERM ) {
+    if ( gid && gid != st.st_gid && lchown( ".", uid, gid ) < 0 && errno != EPERM ) {
         LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
             uid, gid, fullpathname("."), strerror(errno) );
     }
@@ -569,7 +569,7 @@ static int recursive_chown(const char *path, uid_t uid, gid_t gid) {
        return -1;
     }
 
-    if (stat(path, &sbuf) < 0) {
+    if (lstat(path, &sbuf) < 0) {
        LOG(log_error, logtype_afpd, "cannot chown() file [%s] (uid = %d): %s", path, uid, strerror(errno));
        return -1;
     }
index 8ead1c4de02b7663577393d5f2861493327d7d7f..fbf53a1c34ce2c78b6d858fbe20ae8ddacada4cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.52 2010-01-05 12:06:34 franklahm Exp $
+ * $Id: adouble.h,v 1.53 2010-02-10 14:05:37 franklahm Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -249,6 +249,7 @@ struct ad_fd {
     off_t        adf_off;
 #endif
 
+    char         *adf_syml;
     int          adf_flags;
     int          adf_excl;
     adf_lock_t   *adf_lock;
index a938331521874ea4bb48969ad5aa5a61d7261ea7..3569e8695633e805d16c7aff6efd264f5e3eabe5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_flush.c,v 1.12 2009-10-13 22:55:37 didg Exp $
+ * $Id: ad_flush.c,v 1.13 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -200,9 +200,14 @@ int ad_close( struct adouble *ad, int adflags)
 
     if (( adflags & ADFLAGS_DF ) && ad_data_fileno(ad) != -1 &&
         !(--ad->ad_data_fork.adf_refcount)) {
+        if (ad->ad_data_fork.adf_syml!=0){
+            free(ad->ad_data_fork.adf_syml);
+            ad->ad_data_fork.adf_syml=0;
+        }else{     
         if ( close( ad_data_fileno(ad) ) < 0 ) {
             err = -1;
         }
+        }
         ad_data_fileno(ad) = -1;
         adf_lock_free(&ad->ad_data_fork);
     }
index b0eb42350553b2924d2e42e9cbc31a1abcf26691..2785cbf17848f8b790f13d5c0d23cc033781b415 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.68 2010-01-06 14:05:15 franklahm Exp $
+ * $Id: ad_open.c,v 1.69 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -1014,8 +1014,8 @@ int ad_stat(const char *path, struct stat *stbuf)
     if (!p) {
         return -1;
     }
-
-    return stat( p, stbuf );
+//FIXME!
+    return lstat( p, stbuf );
 }
 
 /* ----------------
@@ -1037,7 +1037,7 @@ static int ad_chown(const char *path, struct stat *stbuf)
     if (default_uid != (uid_t)-1) {
         /* we are root (admin) */
         id = (default_uid)?default_uid:stbuf->st_uid;
-        ret = chown( path, id, stbuf->st_gid );
+        ret = lchown( path, id, stbuf->st_gid );
     }
 #endif
     return ret;
@@ -1265,6 +1265,7 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
         ad->ad_adflags = adflags;
         ad->ad_resource_fork.adf_refcount = 0;
         ad->ad_data_fork.adf_refcount = 0;
+        ad->ad_data_fork.adf_syml=0;
     }
     else {
         ad->ad_open_forks = ((ad->ad_data_fork.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
@@ -1283,13 +1284,33 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
                     admode = mode;
                 }
             }
-            ad->ad_data_fork.adf_fd =open( path, hoflags, admode );
+                
+            ad->ad_data_fork.adf_fd =open( path, hoflags | O_NOFOLLOW, admode );
+            
             if (ad->ad_data_fork.adf_fd < 0 ) {
                 if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
                     hoflags = oflags;
-                    ad->ad_data_fork.adf_fd = open( path, hoflags, admode );
+                    ad->ad_data_fork.adf_fd = open( path, hoflags | O_NOFOLLOW, admode );
+                }
+                if (ad->ad_data_fork.adf_fd < 0 && errno == ELOOP) {
+                    int lsz;
+
+                    if (oflags != O_RDONLY)
+                         return -1;
+
+                    ad->ad_data_fork.adf_syml = malloc(PATH_MAX+1);
+                    lsz = readlink(path, ad->ad_data_fork.adf_syml, PATH_MAX);
+                    if (lsz <= 0) {
+                        free(ad->ad_data_fork.adf_syml);
+                        return -1;
+                    }
+                    ad->ad_data_fork.adf_syml[lsz]=0;
+                    ad->ad_data_fork.adf_syml = realloc(ad->ad_data_fork.adf_syml,lsz+1);
+                    // XX
+                    ad->ad_data_fork.adf_fd = 0;
                 }
             }
+
             if ( ad->ad_data_fork.adf_fd < 0)
                 return -1;
 
@@ -1349,11 +1370,11 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
     if (!(adflags & ADFLAGS_RDONLY)) {
         hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
     }
-    ad->ad_md->adf_fd = open( ad_p, hoflags, 0 );
+    ad->ad_md->adf_fd = open( ad_p, hoflags | O_NOFOLLOW, 0 );
     if (ad->ad_md->adf_fd < 0 ) {
         if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
             hoflags = oflags & ~(O_CREAT | O_EXCL);
-            ad->ad_md->adf_fd = open( ad_p, hoflags, 0 );
+            ad->ad_md->adf_fd = open( ad_p, hoflags | O_NOFOLLOW, 0 );
         }
     }
 
@@ -1618,7 +1639,7 @@ static int new_rfork(const char *path, struct adouble *ad, int adflags)
         memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
     }
 
-    if (stat(path, &st) < 0) {
+    if (lstat(path, &st) < 0) {
         return -1;
     }
 
index 19d6218f3e6ff28c0ef95c4423ce39b99e35491d..17c2361faa99a775fef26c000bfb1ff82a8b2675 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_read.c,v 1.9 2009-10-13 22:55:37 didg Exp $
+ * $Id: ad_read.c,v 1.10 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -66,7 +66,16 @@ ssize_t ad_read( struct adouble *ad, const u_int32_t eid, off_t off, char *buf,
     /* 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_data_fork, buf, buflen, off);
+        if (ad->ad_data_fork.adf_syml !=0 ) {
+            /* It's a symlink, we already have the target in adf_syml */
+            cc = strlen(ad->ad_data_fork.adf_syml);
+            if (buflen < cc)
+                /* Request buffersize is too small, force AFPERR_PARAM */
+                return -1;
+            memcpy(buf, ad->ad_data_fork.adf_syml, cc);
+        } else {
+            cc = adf_pread(&ad->ad_data_fork, buf, buflen, off);
+        }
     } else {
         off_t r_off;
 
index 8d1a1f0dd37363e9804bcf2559a0fdeca7926c05..70d281068f766c4ae437eebd161fe418138e09ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: ea.c,v 1.18 2009-12-10 17:40:25 franklahm Exp $
+  $Id: ea.c,v 1.19 2010-02-10 14:05:37 franklahm Exp $
   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -1483,7 +1483,7 @@ int ea_chown(VFS_FUNC_ARGS_CHOWN)
         }
     }
 
-    if ((chown(ea_path(&ea, NULL, 0), uid, gid)) != 0) {
+    if ((lchown(ea_path(&ea, NULL, 0), uid, gid)) != 0) {
         switch (errno) {
         case EPERM:
         case EACCES:
@@ -1500,7 +1500,7 @@ int ea_chown(VFS_FUNC_ARGS_CHOWN)
             ret = AFPERR_MISC;
             goto exit;
         }
-        if ((chown(eaname, uid, gid)) != 0) {
+        if ((lchown(eaname, uid, gid)) != 0) {
             switch (errno) {
             case EPERM:
             case EACCES:
index 35363049c5b486da79f7901e9a77803c64782f88..991d04a01a8f6b4c99ced2c7bb8a9cb9ff89e7e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.c,v 1.8 2010-01-26 08:14:09 didg Exp $
+ * $Id: unix.c,v 1.9 2010-02-10 14:05:37 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -80,19 +80,18 @@ int dir_rx_set(mode_t mode)
 int setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
 {
     struct stat sb;
-    mode_t result = mode;
     mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO;  /* rwx for owner group and other, by default */
 
     if (!st) {
-        if (stat(name, &sb) != 0)
+        if (lstat(name, &sb) != 0)
             return -1;
         st = &sb;
     }
 
-    result |= st->st_mode & ~mask; /* keep other bits from previous mode */
-
-    LOG(log_debug, logtype_afpd, "setfilmode('%s', mode:%04o, vmask:%04o) {st_mode:%04o, chmod:%04o}",
-        fullpathname(name), mode, v_umask, st->st_mode, result);
+    if (S_ISLNK(st->st_mode))
+        return 0; /* we don't want to change link permissions */
+    
+    mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
 
     if ( chmod( name,  mode & ~v_umask ) < 0 && errno != EPERM ) {
         return -1;