/*
- * $Id: afs.c,v 1.10 2002-03-24 01:23:40 sibaz Exp $
+ * $Id: afs.c,v 1.11 2002-08-29 18:57:26 didg Exp $
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
*/
* VIOCGETAL. If the directory is on AFS, use access() calls to
* estimate permission, a la mdw.
*/
-afsmode( path, ma, dir )
+#ifdef accessmode
+ #undef accessmode
+#endif
+
+afsmode( path, ma, dir, st )
char *path;
struct maccess *ma;
-struct dir *dir;
+struct dir *dir;
+struct stat *st;
{
struct ViceIoctl vi;
char buf[ 1024 ];
return;
}
- accessmode( path, &ma, dir );
+ accessmode( path, &ma, dir, st );
return;
}
/*
- * $Id: directory.c,v 1.37 2002-08-22 13:41:19 didg Exp $
+ * $Id: directory.c,v 1.38 2002-08-29 18:57:26 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
break;
case DIRPBIT_ACCESS :
- utommode( st, &ma );
-#ifndef SENDFILE_FLAVOR_LINUX /* ignore this section if it's linux */
-#ifdef HAVE_ACCESS
- accessmode( upath, &ma, dir );
-#endif /* HAVE_ACCESS */
-#endif /* SENDFILE_FLAVOR_LINUX */
-#ifdef AFS /* If only AFS defined, access() works only for AFS filesystems */
- afsmode( upath, &ma, dir );
-#endif /* AFS */
+ accessmode( upath, &ma, dir , st);
+
*data++ = ma.ma_user;
*data++ = ma.ma_world;
*data++ = ma.ma_group;
/*
- * $Id: file.c,v 1.51 2002-08-28 15:08:16 didg Exp $
+ * $Id: file.c,v 1.52 2002-08-29 18:57:26 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
u_int32_t aint;
u_int16_t ashort;
u_char achar, fdType[4];
+ struct maccess ma;
#ifdef DEBUG
LOG(log_info, logtype_afpd, "begin getmetadata:");
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
+#if 0
+ /* FIXME do we want a visual clue if the file is read only
+ */
+ accessmode( ".", &ma, dir , NULL);
+ if ((ma.ma_user & AR_UWRITE)) {
+ accessmode( upath, &ma, dir , st);
+ if (!(ma.ma_user & AR_UWRITE)) {
+ attrbits |= ATTRBIT_NOWRITE;
+ }
+ }
+#endif
if (attrbits)
ashort = htons(ntohs(ashort) | attrbits);
memcpy(data, &ashort, sizeof( ashort ));
set_uidgid ( vol );
#endif /* FORCE_UIDGID */
+ if (check_access(upath, OPENACC_WR ) < 0) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif /* FORCE_UIDGID */
+ return AFPERR_ACCESS;
+ }
+
if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
O_RDWR|O_CREAT, 0666, adp) < 0) {
/* for some things, we don't need an adouble header */
* and the new mac name.
* NOTE: if we have to copy a file instead of renaming it, locks
* will break. Anyway it's an error because then we have 2 files.
- * FIXME: locks on ressource fork will always break thanks to ad_close, done ?
*
- * src the full source absolute path
+ * src the source path
* dst the dest filename in current dir
* newname the dest mac name
* adp adouble struct of src file, if open, or & zeroed one
case EROFS:
return AFPERR_VLOCK;
case EXDEV : /* Cross device move -- try copy */
- /* if source is open bail out */
if (( rc = copyfile(src, dst, newname, noadouble )) != AFP_OK ) {
deletefile( dst, 0 );
return( rc );
return( AFPERR_NOOBJ );
}
if ( *path != '\0' ) {
- return( AFPERR_BADTYPE );
+ return( AFPERR_BADTYPE ); /* not a directory. AFPERR_PARAM? */
}
/* one of the handful of places that knows about the path type */
if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
strncpy( newname, ibuf, plen );
newname[ plen ] = '\0';
+ if (strlen(newname) != plen) {
+ /* there's \0 in newname, e.g. it's a pathname not
+ * only a filename.
+ */
+ return( AFPERR_PARAM );
+ }
}
if ( (err = copyfile(p, mtoupath(vol, newname ), newname,
char filebuf[8192];
int sfd, dfd, len, err = AFP_OK;
ssize_t cc;
-
+ char *dpath;
+ int admode;
#ifdef DEBUG
LOG(log_info, logtype_afpd, "begin copyfile:");
#endif /* DEBUG */
+ dpath = ad_path( dst, ADFLAGS_HF );
+ admode = ad_mode( dst, 0666 );
if (newname) {
if ((sfd = open( ad_path( src, ADFLAGS_HF ), O_RDONLY, 0 )) < 0 ) {
switch ( errno ) {
return( AFPERR_PARAM );
}
} else {
- if (( dfd = open( ad_path( dst, ADFLAGS_HF ), O_WRONLY|O_CREAT,
- ad_mode( ad_path( dst, ADFLAGS_HF ), 0666 ))) < 0 ) {
+ if (( dfd = open( dpath, O_WRONLY|O_CREAT,ad_hf_mode(admode))) < 0 ) {
close( sfd );
switch ( errno ) {
case ENOENT :
close(sfd);
close(dfd);
if (err < 0) {
- unlink(ad_path(dst, ADFLAGS_HF));
+ unlink(dpath);
return err;
}
}
}
}
- if (( dfd = open( dst, O_WRONLY|O_CREAT, ad_mode( dst, 0666 ))) < 0 ) {
+ if (( dfd = open( dst, O_WRONLY|O_CREAT, admode)) < 0 ) {
close( sfd );
switch ( errno ) {
case ENOENT :
close(sfd);
close(dfd);
if (err < 0) {
- unlink(ad_path(dst, ADFLAGS_HF));
+ unlink(dpath);
unlink(dst);
return err;
}
ie deletfile called by afp_delete
when deletefile is called we don't have lock on it, file is closed (for us)
+ untrue if called by renamefile
*/
int deletefile( file, checkAttrib )
char *file;
ibuf += sizeof(id);
if ((upath = cnid_resolve(vol->v_db, &id, buffer, len)) == NULL) {
- return AFPERR_BADID;
+ return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
}
if (( dir = dirlookup( vol, id )) == NULL ) {
- return( AFPERR_PARAM );
+ return AFPERR_NOID; /* idem AFPERR_PARAM */
}
if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
/*
- * $Id: filedir.c,v 1.27 2002-05-13 04:59:36 jmarcus Exp $
+ * $Id: filedir.c,v 1.28 2002-08-29 18:57:26 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
return( AFP_OK );
}
+/*
+ * We can't use unix file's perm to support Apple's inherited protection modes.
+ * If we aren't the file's owner we can't change its perms when moving it and smb
+ * nfs,... don't even try.
+*/
+#define AFP_CHECK_ACCESS
+
+int check_access(char *path, int mode)
+{
+#ifdef AFP_CHECK_ACCESS
+struct maccess ma;
+char *p;
+
+ p = ad_dir(path);
+ if (!p)
+ return -1;
+
+ accessmode(p, &ma, curdir, NULL);
+ if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
+ return -1;
+ if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
+ return -1;
+#endif
+ return 0;
+}
+
int afp_setfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
AFPObj *obj;
char *ibuf, *rbuf;
vol_noadouble(vol), adp )) == AFP_OK) {
/* if it's still open, rename the ofork as well. */
rc = of_rename(vol, sdir, oldname, curdir, newname);
+
}
} else {
rc = renamedir(p, upath, sdir, curdir, newname, vol_noadouble(vol));
if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
strncpy( newname, ibuf, plen );
newname[ plen ] = '\0';
+ if (strlen(newname) != plen) {
+ return( AFPERR_PARAM );
+ }
}
else {
return AFP_OK; /* newname == oldname same dir */
if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
strncpy( newname, ibuf, plen );
newname[ plen ] = '\0';
+ if (strlen(newname) != plen) {
+ return( AFPERR_PARAM );
+ }
}
else {
strcpy(newname, oldname);
return retvalue;
}
}
+ else
#endif /* DROPKLUDGE */
+ if (!isdir) {
+ char *upath = mtoupath(vol, newname);
+ int admode = ad_mode("", 0777);
+
+ setfilmode(upath, admode, NULL);
+ setfilmode(ad_path( upath, ADFLAGS_HF ), ad_hf_mode(admode), NULL);
+ }
setvoltime(obj, vol );
}
/*
- * $Id: filedir.h,v 1.7 2002-05-13 04:59:36 jmarcus Exp $
+ * $Id: filedir.h,v 1.8 2002-08-29 18:57:26 didg Exp $
*/
#ifndef AFPD_FILEDIR_H
char *));
extern int veto_file __P((const char *veto_str, const char *path));
extern int check_name __P((const struct vol *vol, char *name));
+extern int check_access __P((char *name , int mode));
/* FP functions */
extern int matchfile2dirperms __P((char *, struct vol *, int));
/*
- * $Id: fork.c,v 1.33 2002-08-26 08:57:50 didg Exp $
+ * $Id: fork.c,v 1.34 2002-08-29 18:57:26 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
adflags = ADFLAGS_HF;
}
+ upath = mtoupath(vol, path);
+ if (check_access(upath, access ) < 0) {
+ return AFPERR_ACCESS;
+ }
/* XXX: this probably isn't the best way to do this. the already
open bits should really be set if the fork is opened by any
program, not just this one. however, that's problematic to do
adsame)) == NULL ) {
return( AFPERR_NFILE );
}
+
if (access & OPENACC_WR) {
/* try opening in read-write mode */
- upath = mtoupath(vol, path);
ret = AFPERR_NOOBJ;
if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
switch ( errno ) {
}
} else {
/* try opening in read-only mode */
- upath = mtoupath(vol, path);
ret = AFPERR_NOOBJ;
if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
switch ( errno ) {
/*
- * $Id: unix.c,v 1.35 2002-06-06 10:14:26 didg Exp $
+ * $Id: unix.c,v 1.36 2002-08-29 18:57:26 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <netatalk/endian.h>
#include <dirent.h>
#include <limits.h>
+#include <atalk/adouble.h>
#include <atalk/afp.h>
/* STDC check */
struct stat *stat;
struct maccess *ma;
{
- mode_t mode;
+mode_t mode;
mode = stat->st_mode;
-
ma->ma_world = utombits( mode );
mode = mode >> 3;
ma->ma_owner = utombits( mode );
/* ma_user is a union of all permissions */
-
+ ma->ma_user = 0;
if ( (uuid == stat->st_uid) || (uuid == 0)) {
ma->ma_user = ma->ma_owner | AR_UOWN;
}
* Note: the previous method, using access(), does not work correctly
* over NFS.
*/
-void accessmode( path, ma, dir )
+void accessmode( path, ma, dir, st )
char *path;
struct maccess *ma;
-struct dir *dir;
+struct dir *dir;
+struct stat *st;
+
{
- struct stat sb;
- ma->ma_user = ma->ma_owner = 0;
- if ( stat( path, &sb ) == 0 )
- utommode( &sb, ma );
+struct stat sb;
+
+ ma->ma_user = ma->ma_owner = ma->ma_world = ma->ma_group = 0;
+ if (!st) {
+ if (stat(path, &sb) != 0)
+ return;
+ st = &sb;
+ }
+ utommode( st, ma );
return;
}
return( 0 );
}
+int setfilmode(name, mode, st)
+char * name;
+mode_t mode;
+struct stat *st;
+{
+struct stat sb;
+mode_t mask = S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH;
+
+ if (!st) {
+ if (stat(name, &sb) != 0)
+ return;
+ st = &sb;
+ }
+ mode &= mask; /* keep only rw-rw-rw in mode */
+ mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
+ if ( chmod( name, mode & ~default_options.umask ) < 0 && errno != EPERM ) {
+ return -1;
+ }
+ return 0;
+}
+
int setdirmode( mode, noadouble, dropbox )
const mode_t mode;
const int noadouble;
char *m;
struct dirent *dirp;
DIR *dir;
-
+
if (( dir = opendir( "." )) == NULL ) {
LOG(log_error, logtype_afpd, "setdirmode: opendir .: %s", strerror(errno) );
return( -1 );
}
if (S_ISREG(st.st_mode)) {
+ if (setfilmode(dirp->d_name, mode, &st) < 0) {
+ LOG(log_error, logtype_afpd, "setdirmode: chmod %s: %s",
+ dirp->d_name, strerror(errno) );
+ return -1;
+ }
+ }
+#if 0
/* XXX: need to preserve special modes */
- if (S_ISDIR(st.st_mode)) {
+ else if (S_ISDIR(st.st_mode)) {
if (stickydirmode(dirp->d_name, DIRBITS | mode, dropbox) < 0)
return (-1);
} else if (stickydirmode(dirp->d_name, mode, dropbox) < 0)
return (-1);
}
+#endif
}
closedir( dir );
+
+ /* change perm of .AppleDouble's files
+ */
if (( dir = opendir( ".AppleDouble" )) == NULL ) {
if (noadouble)
goto setdirmode_noadouble;
LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", buf, strerror(errno) );
continue;
}
-
- if (S_ISDIR(st.st_mode)) {
- stickydirmode( buf, DIRBITS | mode, dropbox );
- } else
- stickydirmode( buf, mode, dropbox );
+ if (S_ISREG(st.st_mode)) {
+ if (setfilmode(dirp->d_name, ad_hf_mode(mode), &st) < 0) {
+ /* FIXME what do we do then? */
+ }
+ }
} /* end for */
closedir( dir );
/*
- * $Id: unix.h,v 1.9 2001-12-03 05:03:38 jmarcus Exp $
+ * $Id: unix.h,v 1.10 2002-08-29 18:57:26 didg Exp $
*/
#ifndef AFPD_UNIX_H
extern int setdirmode __P((const mode_t, const int, const int));
extern int setdeskowner __P((const uid_t, const gid_t));
extern int setdirowner __P((const uid_t, const gid_t, const int));
+extern int setfilmode __P((char *, mode_t , struct stat *));
+
+extern void accessmode __P((char *, struct maccess *, struct dir *, struct stat *));
+
+#ifdef AFS
+ #define accessmode afsmode
+#endif
#endif /* UNIX_H */
/*
- * $Id: adouble.h,v 1.8 2002-05-13 07:21:55 jmarcus Exp $
+ * $Id: adouble.h,v 1.9 2002-08-29 18:57:36 didg Exp $
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
#include <fcntl.h>
#include <sys/cdefs.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/mman.h>
#include <netatalk/endian.h>
#endif
/* ad_open.c */
+extern char *ad_dir __P((char *));
extern char *ad_path __P((char *, int));
extern int ad_mode __P((char *, int));
extern int ad_mkdir __P((char *, int));
extern int ad_open __P((char *, int, int, int, struct adouble *));
extern int ad_refresh __P((struct adouble *));
+/* extend to RW if R for locking */
+static inline mode_t ad_hf_mode (mode_t mode)
+{
+#ifndef USE_FLOCK_LOCKS
+ /* fnctl lock need write access */
+ if ((mode & S_IRUSR))
+ mode |= S_IWUSR;
+ if ((mode & S_IRGRP))
+ mode |= S_IWGRP;
+ if ((mode & S_IROTH))
+ mode |= S_IWOTH;
+#endif
+ return mode;
+}
+
/* ad_read.c/ad_write.c */
extern ssize_t ad_read __P((struct adouble *, const u_int32_t,
const off_t, char *, const size_t));
/*
- * $Id: ad_open.c,v 1.18 2002-08-14 10:35:46 didg Exp $
+ * $Id: ad_open.c,v 1.19 2002-08-29 18:57:37 didg Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
* Copyright (c) 1990,1991 Regents of The University of Michigan.
#define DEFMASK 07700 /* be conservative */
-int
-ad_mode( path, mode )
+char
+*ad_dir(path)
char *path;
- int mode;
{
static char modebuf[ MAXPATHLEN + 1];
- struct stat stbuf;
char *slash;
- if ( mode == 0 ) {
- return( mode ); /* save on syscalls */
- }
-
if ( strlen( path ) >= MAXPATHLEN ) {
- return( mode & DEFMASK ); /* can't do it */
+ return NULL; /* can't do it */
}
/*
modebuf[0] = '.'; /* use current directory */
modebuf[1] = '\0';
}
+ return modebuf;
+}
+
+int
+ad_mode( path, mode )
+ char *path;
+ int mode;
+{
+ struct stat stbuf;
+ char *p;
+
+ if ( mode == 0 ) {
+ return( mode ); /* save on syscalls */
+ }
+ p = ad_dir(path);
+ if (!p) {
+ return( mode & DEFMASK ); /* can't do it */
+ }
- if ( stat( modebuf, &stbuf ) != 0 ) {
+ if ( stat( p, &stbuf ) != 0 ) {
return( mode & DEFMASK ); /* bail out... can't stat dir? */
}
if (adflags & ADFLAGS_DF) {
if (ad_dfileno(ad) == -1) {
hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
- if (( ad->ad_df.adf_fd =
- open( path, hoflags, ad_mode( path, mode ) )) < 0 ) {
+ admode = ad_mode( path, mode );
+ if (( ad->ad_df.adf_fd = open( path, hoflags, admode )) < 0 ) {
if (errno == EACCES && !(oflags & O_RDWR)) {
hoflags = oflags;
- ad->ad_df.adf_fd =open( path, hoflags, ad_mode( path, mode ) );
+ ad->ad_df.adf_fd =open( path, hoflags, admode );
}
}
if ( ad->ad_df.adf_fd < 0)
if (adflags & ADFLAGS_HF) {
if (ad_hfileno(ad) == -1) {
ad_p = ad_path( path, adflags );
- admode = ad_mode( ad_p, mode ); /* FIXME? */
+
hoflags = oflags & ~O_CREAT;
hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
- if (( ad->ad_hf.adf_fd = open( ad_p, hoflags, admode )) < 0 ) {
- if (errno == EACCES) {
- if (!(oflags & O_RDWR)) {
- hoflags = oflags & ~O_CREAT;
- ad->ad_hf.adf_fd = open( ad_p, hoflags, admode );
- }
+ if (( ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 )) < 0 ) {
+ if (errno == EACCES && !(oflags & O_RDWR)) {
+ hoflags = oflags & ~O_CREAT;
+ ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 );
}
}
if ( ad->ad_hf.adf_fd < 0 ) {
* here.
* if ((oflags & O_CREAT) ==> (oflags & O_RDWR)
*/
+ admode = ad_hf_mode(ad_mode( ad_p, mode ));
errno = 0;
if (( ad->ad_hf.adf_fd = open( ad_p, oflags,
admode )) < 0 ) {