From: didg Date: Thu, 29 Aug 2002 18:57:26 +0000 (+0000) Subject: try to make afpd directory access right works the way Macs expect X-Git-Tag: point-did-cleanup~37 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=85b1a6bd6e3d8cbc7eff992f763a1d57b3a0f459 try to make afpd directory access right works the way Macs expect --- diff --git a/etc/afpd/afs.c b/etc/afpd/afs.c index 4c80d069..5727ccc3 100644 --- a/etc/afpd/afs.c +++ b/etc/afpd/afs.c @@ -1,5 +1,5 @@ /* - * $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. */ @@ -123,10 +123,15 @@ int ibuflen, *rbuflen; * 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 ]; @@ -146,7 +151,7 @@ struct dir *dir; return; } - accessmode( path, &ma, dir ); + accessmode( path, &ma, dir, st ); return; } diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 0ef58ce0..02fb04fe 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -1,5 +1,5 @@ /* - * $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. @@ -1109,15 +1109,8 @@ int getdirparams(const struct vol *vol, 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; diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 2d1871e3..7053464c 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -1,5 +1,5 @@ /* - * $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. @@ -110,6 +110,7 @@ int getmetadata(struct vol *vol, 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:"); @@ -132,6 +133,17 @@ int getmetadata(struct vol *vol, 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 )); @@ -655,6 +667,13 @@ int setfilparams(struct vol *vol, 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 */ @@ -821,9 +840,8 @@ setfilparam_done: * 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 @@ -860,7 +878,6 @@ struct adouble *adp; 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 ); @@ -994,7 +1011,7 @@ int ibuflen, *rbuflen; 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 */ @@ -1004,6 +1021,12 @@ int ibuflen, *rbuflen; 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, @@ -1072,11 +1095,14 @@ const int noadouble; 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 ) { @@ -1088,8 +1114,7 @@ const int noadouble; 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 : @@ -1139,7 +1164,7 @@ copyheader_done: close(sfd); close(dfd); if (err < 0) { - unlink(ad_path(dst, ADFLAGS_HF)); + unlink(dpath); return err; } } @@ -1157,7 +1182,7 @@ copyheader_done: } } - 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 : @@ -1206,7 +1231,7 @@ copydata_done: close(sfd); close(dfd); if (err < 0) { - unlink(ad_path(dst, ADFLAGS_HF)); + unlink(dpath); unlink(dst); return err; } @@ -1247,6 +1272,7 @@ copydata_done: 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; @@ -1527,11 +1553,11 @@ int ibuflen, *rbuflen; 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)) { diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index b4e61667..7d690a9f 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -1,5 +1,5 @@ /* - * $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. @@ -232,6 +232,32 @@ int ibuflen, *rbuflen; 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; @@ -409,6 +435,7 @@ int isdir; 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)); @@ -494,6 +521,9 @@ int ibuflen, *rbuflen; 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 */ @@ -682,6 +712,9 @@ int ibuflen, *rbuflen; if (( plen = (unsigned char)*ibuf++ ) != 0 ) { strncpy( newname, ibuf, plen ); newname[ plen ] = '\0'; + if (strlen(newname) != plen) { + return( AFPERR_PARAM ); + } } else { strcpy(newname, oldname); @@ -696,7 +729,15 @@ int ibuflen, *rbuflen; 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 ); } diff --git a/etc/afpd/filedir.h b/etc/afpd/filedir.h index f1ef1f6c..a64c8fd9 100644 --- a/etc/afpd/filedir.h +++ b/etc/afpd/filedir.h @@ -1,5 +1,5 @@ /* - * $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 @@ -16,6 +16,7 @@ extern char *ctoupath __P((const struct vol *, struct dir *, 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)); diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 32ba4812..4aaee868 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $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. @@ -277,6 +277,10 @@ int ibuflen, *rbuflen; 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 @@ -295,9 +299,9 @@ int ibuflen, *rbuflen; 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 ) { @@ -345,7 +349,6 @@ int ibuflen, *rbuflen; } } 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 ) { diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c index c5459c16..7f948bc9 100644 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@ -1,5 +1,5 @@ /* - * $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. @@ -20,6 +20,7 @@ #include #include #include +#include #include /* STDC check */ @@ -121,10 +122,9 @@ void utommode( stat, ma ) struct stat *stat; struct maccess *ma; { - mode_t mode; +mode_t mode; mode = stat->st_mode; - ma->ma_world = utombits( mode ); mode = mode >> 3; @@ -134,7 +134,7 @@ struct maccess *ma; 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; } @@ -165,15 +165,22 @@ struct maccess *ma; * 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; } @@ -353,6 +360,27 @@ const mode_t mode; 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; @@ -363,7 +391,7 @@ const int dropbox; char *m; struct dirent *dirp; DIR *dir; - + if (( dir = opendir( "." )) == NULL ) { LOG(log_error, logtype_afpd, "setdirmode: opendir .: %s", strerror(errno) ); return( -1 ); @@ -380,15 +408,26 @@ const int dropbox; } 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; @@ -410,11 +449,11 @@ const int dropbox; 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 ); diff --git a/etc/afpd/unix.h b/etc/afpd/unix.h index a846eb89..3373aa65 100644 --- a/etc/afpd/unix.h +++ b/etc/afpd/unix.h @@ -1,5 +1,5 @@ /* - * $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 @@ -98,5 +98,12 @@ extern int setdeskmode __P((const mode_t)); 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 */ diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index cc5cd15d..93acdcb1 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -1,5 +1,5 @@ /* - * $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. * @@ -39,6 +39,7 @@ extern int flock (int /*fd*/, int /*operation*/); #include #include #include +#include #include #include @@ -287,12 +288,28 @@ extern int ad_fcntl_tmplock __P((struct adouble *, const u_int32_t /*eid*/, #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)); diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 990e3a4d..1fe07ca4 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -1,5 +1,5 @@ /* - * $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. @@ -530,21 +530,15 @@ ad_path( path, adflags ) #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 */ } /* @@ -559,8 +553,26 @@ ad_mode( path, mode ) 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? */ } @@ -612,11 +624,11 @@ int ad_open( path, adflags, oflags, mode, ad ) 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) @@ -639,15 +651,13 @@ int ad_open( path, adflags, oflags, mode, ad ) 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 ) { @@ -657,6 +667,7 @@ int ad_open( path, adflags, oflags, mode, ad ) * 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 ) {