X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fdirectory.c;h=0a5f0893fe71f5934556f2fb94188d99e066a502;hb=5447b10e1ea30a83c7af9790b557fea7337be400;hp=9f3798503f121226b4bf7486348bff5b2ff64af5;hpb=728e143736a502a3fa1a6f46b38b56b631edffea;p=netatalk.git diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 9f379850..0a5f0893 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -1,5 +1,5 @@ /* - * $Id: directory.c,v 1.71.2.4.2.15.2.5 2005-02-10 01:23:10 didg Exp $ + * $Id: directory.c,v 1.71.2.4.2.15.2.14 2009-09-07 11:35:04 franklahm Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -392,9 +392,7 @@ struct dir *dir; /* remove the node from the tree. this is just like insertion, but * different. actually, it has to worry about a bunch of things that * insertion doesn't care about. */ -static void dir_remove( vol, dir ) -struct vol *vol; -struct dir *dir; +static void dir_remove( const struct vol *vol _U_, struct dir *dir) { #ifdef REMOVE_NODES struct ofork *of, *last; @@ -571,6 +569,15 @@ struct path *path; afp_errno = AFPERR_PARAM; return NULL; } + + if (check_name(vol, path->u_name)) { + /* the name is illegal */ + LOG(log_info, logtype_afpd, "extenddir: illegal path: '%s'", path->u_name); + path->u_name = NULL; + afp_errno = AFPERR_PARAM; + return NULL; + } + if (of_stat( path ) != 0 ) { return( NULL ); } @@ -1116,7 +1123,7 @@ char **cpath; static char temp[ MAXPATHLEN + 1]; /* not an UTF8 name */ - if (mtoUTF8(vol, path, strlen(path), temp, MAXPATHLEN) == -1) { + if (mtoUTF8(vol, path, strlen(path), temp, MAXPATHLEN) == (size_t)-1) { afp_errno = AFPERR_PARAM; return( NULL ); } @@ -1290,6 +1297,12 @@ struct maccess ma; } +/* --------------------- */ +static int invisible_dots(const struct vol *vol, const char *name) +{ + return vol_inv_dots(vol) && *name == '.' && strcmp(name, ".") && strcmp(name, ".."); +} + /* ------------------------------ (".", curdir) (name, dir) with curdir:name == dir, from afp_enumerate @@ -1343,8 +1356,7 @@ int getdirparams(const struct vol *vol, case DIRPBIT_ATTR : if ( isad ) { ad_getattr(&ad, &ashort); - } else if (*dir->d_u_name == '.' && strcmp(dir->d_u_name, ".") - && strcmp(dir->d_u_name, "..")) { + } else if (invisible_dots(vol, dir->d_u_name)) { ashort = htons(ATTRBIT_INVISIBLE); } else ashort = 0; @@ -1387,12 +1399,10 @@ int getdirparams(const struct vol *vol, ashort = htons(FINDERINFO_CLOSEDVIEW); memcpy(data + FINDERINFO_FRVIEWOFF, &ashort, sizeof(ashort)); - /* dot files are by default invisible */ - if (*dir->d_u_name == '.' && strcmp(dir->d_u_name , ".") && - strcmp(dir->d_u_name , "..")) { + /* dot files are by default visible */ + if (invisible_dots(vol, dir->d_u_name)) { ashort = htons(FINDERINFO_INVISIBLE); - memcpy(data + FINDERINFO_FRFLAGOFF, - &ashort, sizeof(ashort)); + memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort)); } } data += 32; @@ -1542,9 +1552,9 @@ int path_error(struct path *path, int error) /* ----------------------------- */ int afp_setdirparams(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +AFPObj *obj; +char *ibuf, *rbuf _U_; +int ibuflen _U_, *rbuflen; { struct vol *vol; struct dir *dir; @@ -1610,8 +1620,9 @@ struct path Cur_Path = { 0, "", /* mac name */ ".", /* unix name */ + NULL, 0, /* stat is not set */ - 0, /* */ + 0 /* errno */ }; /* ------------------ */ @@ -1639,7 +1650,7 @@ int setdirparams(const struct vol *vol, char *upath; struct dir *dir; - int bit, aint, isad = 1; + int bit, isad = 1; int cdate, bdate; int owner, group; u_int16_t ashort, bshort; @@ -1650,7 +1661,7 @@ int setdirparams(const struct vol *vol, u_int16_t bitmap = d_bitmap; u_char finder_buf[32]; u_int32_t upriv; - mode_t mpriv; /* uninitialized, OK 310105 */ + mode_t mpriv = 0; u_int16_t upriv_bit = 0; bit = 0; @@ -1704,7 +1715,7 @@ int setdirparams(const struct vol *vol, ma.ma_world = *buf++; ma.ma_group = *buf++; ma.ma_owner = *buf++; - mpriv = mtoumode( &ma ); + mpriv = mtoumode( &ma ) | vol->v_dperm; if (dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) { err = set_dir_errors(path, "setdirmode", errno); bitmap = 0; @@ -1724,20 +1735,21 @@ int setdirparams(const struct vol *vol, break; case DIRPBIT_UNIXPR : if (vol_unix_priv(vol)) { - /* Skip UID and GID for now, there seems to be no way to set them from an OSX client anyway */ - buf += sizeof( aint ); - buf += sizeof( aint ); + memcpy( &owner, buf, sizeof(owner)); /* FIXME need to change owner too? */ + buf += sizeof( owner ); + memcpy( &group, buf, sizeof( group )); + buf += sizeof( group ); change_mdate = 1; change_parent_mdate = 1; memcpy( &upriv, buf, sizeof( upriv )); buf += sizeof( upriv ); - upriv = ntohl (upriv); + upriv = ntohl (upriv) | vol->v_dperm; if (dir_rx_set(upriv)) { /* maybe we are trying to set perms back */ if ( setdirunixmode(vol, upath, upriv) < 0 ) { bitmap = 0; - err = set_dir_errors(path, "setdirmode", errno); + err = set_dir_errors(path, "setdirunixmode", errno); } } else { @@ -1855,27 +1867,14 @@ int setdirparams(const struct vol *vol, goto setdirparam_done; } break; - case DIRPBIT_GID : if (dir->d_did == DIRDID_ROOT) setdeskowner( -1, ntohl(group) ); - -#if 0 /* don't error if we can't set the desktop owner. */ - err = set_dir_errors(path, "setdeskowner", errno); - if (isad && err == AFPERR_PARAM) { - err = AFP_OK; /* ???*/ - } - else { - goto setdirparam_done; - } -#endif /* 0 */ - if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) { err = set_dir_errors(path, "setdirowner", errno); goto setdirparam_done; } break; - case DIRPBIT_ACCESS : if (dir->d_did == DIRDID_ROOT) { setdeskmode(mpriv); @@ -1900,21 +1899,29 @@ int setdirparams(const struct vol *vol, case DIRPBIT_UNIXPR : if (vol_unix_priv(vol)) { if (dir->d_did == DIRDID_ROOT) { - setdeskmode( upriv ); if (!dir_rx_set(upriv)) { /* we can't remove read and search for owner on volume root */ err = AFPERR_ACCESS; goto setdirparam_done; } + setdeskowner( -1, ntohl(group) ); + setdeskmode( upriv ); + } + if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) { + err = set_dir_errors(path, "setdirowner", errno); + goto setdirparam_done; } if ( upriv_bit && setdirunixmode(vol, upath, upriv) < 0 ) { - err = set_dir_errors(path, "setdirmode", errno); + err = set_dir_errors(path, "setdirunixmode", errno); goto setdirparam_done; } - break; } - /* fall through */ + else { + err = AFPERR_BITMAP; + goto setdirparam_done; + } + break; default : err = AFPERR_BITMAP; goto setdirparam_done; @@ -1962,10 +1969,103 @@ setdirparam_done: return err; } +int afp_syncdir(obj, ibuf, ibuflen, rbuf, rbuflen ) +AFPObj *obj _U_; +char *ibuf, *rbuf _U_; +int ibuflen _U_, *rbuflen; +{ +#ifdef HAVE_DIRFD + DIR *dp; +#endif + int dfd; + struct vol *vol; + struct dir *dir; + u_int32_t did; + u_int16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == (vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + + /* + * Here's the deal: + * if it's CNID 2 our only choice to meet the specs is call sync. + * For any other CNID just sync that dir. To my knowledge the + * intended use of FPSyncDir is to sync the volume so all we're + * ever going to see here is probably CNID 2. Anyway, we' prepared. + */ + + if ( ntohl(did) == 2 ) { + sync(); + } else { + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; /* was AFPERR_NOOBJ */ + } + + if (movecwd( vol, dir ) < 0 ) + return ( AFPERR_NOOBJ ); + + /* + * Assuming only OSens that have dirfd also may require fsyncing directories + * in order to flush metadata e.g. Linux. + */ + +#ifdef HAVE_DIRFD + if (NULL == ( dp = opendir( "." )) ) { + switch( errno ) { + case ENOENT : + return( AFPERR_NOOBJ ); + case EACCES : + return( AFPERR_ACCESS ); + default : + return( AFPERR_PARAM ); + } + } + + LOG(log_debug, logtype_afpd, "afp_syncdir: dir: '%s'", dir->d_u_name); + + dfd = dirfd( dp ); + if ( fsync ( dfd ) < 0 ) + LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s", + dir->d_u_name, strerror(errno) ); + closedir(dp); /* closes dfd too */ +#endif + + if ( -1 == (dfd = open(vol->ad_path(".", ADFLAGS_DIR), O_RDWR))) { + switch( errno ) { + case ENOENT: + return( AFPERR_NOOBJ ); + case EACCES: + return( AFPERR_ACCESS ); + default: + return( AFPERR_PARAM ); + } + } + + LOG(log_debug, logtype_afpd, "afp_syncdir: ad-file: '%s'", + vol->ad_path(".", ADFLAGS_DIR) ); + + if ( fsync(dfd) < 0 ) + LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s", + vol->ad_path(dir->d_u_name, ADFLAGS_DIR), strerror(errno) ); + close(dfd); + } + + return ( AFP_OK ); +} + int afp_createdir(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; +AFPObj *obj; char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int ibuflen _U_, *rbuflen; { struct adouble ad; struct vol *vol; @@ -2006,9 +2106,6 @@ int ibuflen, *rbuflen; return AFPERR_EXIST; upath = s_path->u_name; - if (0 != (err = check_name(vol, upath))) { - return err; - } if (AFP_OK != (err = netatalk_mkdir( upath))) { return err; @@ -2148,10 +2245,9 @@ struct dir *dir, *newparent; #define DOT_APPLEDOUBLE_LEN 13 /* delete an empty directory */ -int deletecurdir( vol, path, pathlen ) +int deletecurdir( vol, path ) const struct vol *vol; char *path; -int pathlen; { struct dirent *de; struct stat st; @@ -2257,9 +2353,9 @@ delete_done: } int afp_mapid(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; +AFPObj *obj; char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int ibuflen _U_, *rbuflen; { struct passwd *pw; struct group *gr; @@ -2330,9 +2426,9 @@ int ibuflen, *rbuflen; } int afp_mapname(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; +AFPObj *obj _U_; char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int ibuflen _U_, *rbuflen; { struct passwd *pw; struct group *gr; @@ -2394,9 +2490,9 @@ int ibuflen, *rbuflen; variable DID support */ int afp_closedir(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +AFPObj *obj _U_; +char *ibuf _U_, *rbuf _U_; +int ibuflen _U_, *rbuflen; { #if 0 struct vol *vol; @@ -2433,9 +2529,9 @@ int ibuflen, *rbuflen; * there's a pb again with case but move it to cname */ int afp_opendir(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; +AFPObj *obj _U_; char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int ibuflen _U_, *rbuflen; { struct vol *vol; struct dir *parentdir;