* 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
* 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
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
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
-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)
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
/*
- $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
}
/* 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;
/*
- * $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.
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 );
/* -------------------- */
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);
}
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)
/* 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;
}
/* 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;
/* 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)
/* 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;
/*
- * $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.
* 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)
{
break;
}
strcpy(path + len, de->d_name);
- if (stat(path, &st)) {
+ if (lstat(path, &st)) {
continue;
}
if (S_ISDIR(st.st_mode)) {
}
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;
}
/* 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);
}
struct dir *d;
char *p, *u;
int n;
+ int ret;
if ( dir == curdir ) {
return( 0 );
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:
/*
- * $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.
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) {
/*
- * $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.
}
/* 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;
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 ));
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;
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 :
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 */
}
/* FIXME use of_statdir ? */
- if (stat(name, &st)) {
+ if (lstat(name, &st)) {
return -1;
}
}
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:
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) {
/*
- * $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.
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);
/*
- * $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.
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",
/*
- * $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.
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;
}
/* 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;
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;
/*
- * $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.
dev_t devno;
static struct mnttab mnt;
- if ( stat( file, &sb ) < 0 ) {
+ if ( lstat( file, &sb ) < 0 ) {
return( NULL );
}
devno = sb.st_dev;
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 );
struct mntent *mnt;
int found=0;
- if ( stat( file, &sb ) < 0 ) {
+ if ( lstat( file, &sb ) < 0 ) {
return( NULL );
}
devno = sb.st_dev;
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;
/*
- * $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.
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;
}
*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;
}
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;
}
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;
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 */
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) );
}
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;
}
/*
- * $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.
*
off_t adf_off;
#endif
+ char *adf_syml;
int adf_flags;
int adf_excl;
adf_lock_t *adf_lock;
/*
- * $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.
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);
}
/*
- * $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.
if (!p) {
return -1;
}
-
- return stat( p, stbuf );
+//FIXME!
+ return lstat( p, 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;
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);
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;
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 );
}
}
memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
- if (stat(path, &st) < 0) {
+ if (lstat(path, &st) < 0) {
return -1;
}
/*
- * $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.
/* 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;
/*
- $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
}
}
- 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:
ret = AFPERR_MISC;
goto exit;
}
- if ((chown(eaname, uid, gid)) != 0) {
+ if ((lchown(eaname, uid, gid)) != 0) {
switch (errno) {
case EPERM:
case EACCES:
/*
- * $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.
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;