X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fdirectory.c;h=0a5f0893fe71f5934556f2fb94188d99e066a502;hb=5447b10e1ea30a83c7af9790b557fea7337be400;hp=af57b41751eb878dd86ba96c7ed728f603b01e50;hpb=97947cdd4ed4343ec1ae1df25f9f23d9b3f6432b;p=netatalk.git diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index af57b417..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.8 2005-09-27 10:40:41 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 ); } @@ -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; @@ -1610,8 +1620,9 @@ struct path Cur_Path = { 0, "", /* mac name */ ".", /* unix name */ + NULL, 0, /* stat is not set */ - 0, /* */ + 0 /* errno */ }; /* ------------------ */ @@ -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 ) | vol->v_perm; + 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; @@ -1733,7 +1744,7 @@ int setdirparams(const struct vol *vol, change_parent_mdate = 1; memcpy( &upriv, buf, sizeof( upriv )); buf += sizeof( upriv ); - upriv = ntohl (upriv) | vol->v_perm; + 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 ) { @@ -1958,6 +1969,99 @@ 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; char *ibuf, *rbuf; @@ -2002,9 +2106,6 @@ int ibuflen _U_, *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; @@ -2144,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;