X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fextattrs.c;h=40298b50737ccfa62000ac1469c2e4749a4ef511;hp=2cbcec9e44f64ceea3bf8eeea147e55079b2ab74;hb=465246e257d9aff9855e3e35d8fd5983db932b45;hpb=1c144e4ba30d0c68e9035c02f044bf8dbd8bf719 diff --git a/etc/afpd/extattrs.c b/etc/afpd/extattrs.c index 2cbcec9e..40298b50 100644 --- a/etc/afpd/extattrs.c +++ b/etc/afpd/extattrs.c @@ -1,5 +1,5 @@ /* - $Id: extattrs.c,v 1.2 2009-03-03 13:51:25 franklahm Exp $ + $Id: extattrs.c,v 1.29 2010-01-05 12:06:33 franklahm Exp $ Copyright (c) 2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@ -13,42 +13,36 @@ GNU General Public License for more details. */ -/* According to man fsattr.5 we must define _ATFILE_SOURCE */ -#define _ATFILE_SOURCE - #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ -#ifdef HAVE_EXT_ATTRS - -#include #include +#include #include #include -#include -#include -#include -#include #include +#include +#include #include #include +#include +#include -#include "globals.h" #include "volume.h" #include "desktop.h" #include "directory.h" #include "fork.h" #include "extattrs.h" -static char *ea_finderinfo = "com.apple.FinderInfo"; -static char *ea_resourcefork = "com.apple.ResourceFork"; +static const char *ea_finderinfo = "com.apple.FinderInfo"; +static const char *ea_resourcefork = "com.apple.ResourceFork"; /* This should be big enough to consecutively store the names of all attributes */ -#define ATTRNAMEBUFSIZ 4096 static char attrnamebuf[ATTRNAMEBUFSIZ]; +#ifdef DEBUG static void hexdump(void *m, size_t l) { char *p = m; int count = 0, len; @@ -66,216 +60,41 @@ static void hexdump(void *m, size_t l) { } } } - -static int getextattr_size(char *rbuf, int *rbuflen, char *uname, int oflag, char *attruname) -{ - int ret, attrdirfd; - uint32_t attrsize; - struct stat st; - - LOG(log_debug7, logtype_afpd, "getextattr_size(%s): attribute: \"%s\"", uname, attruname); - - if ( -1 == (attrdirfd = attropen(uname, ".", O_RDONLY | oflag))) { - if (errno == ELOOP) { - /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "getextattr_size(%s): encountered symlink with kXAttrNoFollow", uname); - - memset(rbuf, 0, 4); - *rbuflen += 4; - - return AFP_OK; - } - LOG(log_error, logtype_afpd, "getextattr_size: attropen error: %s", strerror(errno)); - return AFPERR_MISC; - } - - if ( -1 == (fstatat(attrdirfd, attruname, &st, 0))) { - LOG(log_error, logtype_afpd, "getextattr_size: fstatat error: %s", strerror(errno)); - ret = AFPERR_MISC; - goto exit; - } - attrsize = (st.st_size > MAX_EA_SIZE) ? MAX_EA_SIZE : st.st_size; - - /* Start building reply packet */ - - LOG(log_debug7, logtype_afpd, "getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, attrsize); - - /* length of attribute data */ - attrsize = htonl(attrsize); - memcpy(rbuf, &attrsize, 4); - *rbuflen += 4; - - ret = AFP_OK; - -exit: - close(attrdirfd); - return ret; -} - -static int getextattr_content(char *rbuf, int *rbuflen, char *uname, int oflag, char *attruname, int maxreply) -{ - int ret, attrdirfd; - size_t toread, okread = 0, len; - char *datalength; - struct stat st; - - if ( -1 == (attrdirfd = attropen(uname, attruname, O_RDONLY | oflag))) { - if (errno == ELOOP) { - /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname); - - memset(rbuf, 0, 4); - *rbuflen += 4; - - return AFP_OK; - } - LOG(log_error, logtype_afpd, "getextattr_content(%s): attropen error: %s", attruname, strerror(errno)); - return AFPERR_MISC; - } - - if ( -1 == (fstat(attrdirfd, &st))) { - LOG(log_error, logtype_afpd, "getextattr_content(%s): fstatat error: %s", attruname,strerror(errno)); - ret = AFPERR_MISC; - goto exit; - } - - /* Start building reply packet */ - - maxreply -= MAX_REPLY_EXTRA_BYTES; - if (maxreply > MAX_EA_SIZE) - maxreply = MAX_EA_SIZE; - - /* But never send more than the client requested */ - toread = (maxreply < st.st_size) ? maxreply : st.st_size; - - LOG(log_debug7, logtype_afpd, "getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply); - - /* remember where we must store length of attribute data in rbuf */ - datalength = rbuf; - rbuf += 4; - *rbuflen += 4; - - while (1) { - len = read(attrdirfd, rbuf, toread); - if (len == -1) { - LOG(log_error, logtype_afpd, "getextattr_content(%s): read error: %s", attruname, strerror(errno)); - ret = AFPERR_MISC; - goto exit; - } - okread += len; - rbuf += len; - *rbuflen += len; - if ((len == 0) || (okread == toread)) - break; - } - - okread = htonl((uint32_t)okread); - memcpy(datalength, &okread, 4); - - ret = AFP_OK; - -exit: - close(attrdirfd); - return ret; -} - -int list_extattr(AFPObj *obj, char *attrnamebuf, int *buflen, char *uname, int oflag) -{ - int ret, attrbuflen = *buflen, len, attrdirfd = 0; - struct dirent *dp; - DIR *dirp = NULL; - - /* Now list file attribute dir */ - if ( -1 == (attrdirfd = attropen( uname, ".", O_RDONLY | oflag))) { - if (errno == ELOOP) { - /* its a symlink and client requested O_NOFOLLOW */ - ret = AFPERR_BADTYPE; - goto exit; - } - LOG(log_error, logtype_afpd, "list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno)); - ret = AFPERR_MISC; - goto exit; - } - - if (NULL == (dirp = fdopendir(attrdirfd))) { - LOG(log_error, logtype_afpd, "list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno)); - ret = AFPERR_MISC; - goto exit; - } - - while ((dp = readdir(dirp))) { - /* check if its "." or ".." */ - if ((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..") == 0) || - (strcmp(dp->d_name, "SUNWattr_ro") == 0) || (strcmp(dp->d_name, "SUNWattr_rw") == 0)) - continue; - - len = strlen(dp->d_name); - - if ( 0 >= ( len = convert_string(obj->options.unixcharset, CH_UTF8_MAC, dp->d_name, len, attrnamebuf + attrbuflen, 255)) ) { - ret = AFPERR_MISC; - goto exit; - } - if (len == 255) - /* convert_string didn't 0-terminate */ - attrnamebuf[attrbuflen + 255] = 0; - - LOG(log_debug7, logtype_afpd, "list_extattr(%s): attribute: %s", uname, dp->d_name); - - attrbuflen += len + 1; - if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { - /* Next EA name could overflow, so bail out with error. - FIXME: evantually malloc/memcpy/realloc whatever. - Is it worth it ? */ - LOG(log_warning, logtype_afpd, "list_extattr(%s): running out of buffer for EA names", uname); - ret = AFPERR_MISC; - goto exit; - } - } - - ret = AFP_OK; - -exit: - if (dirp) - closedir(dirp); - - if (attrdirfd > 0) - close(attrdirfd); - - *buflen = attrbuflen; - return ret; -} +#endif /*************************************** - * Interface + * AFP funcs ****************************************/ -/* - Note: we're being called twice. Firstly the client only want the size of all - EA names, secondly it wants these names. In order to avoid scanning EAs twice - we cache them in a static buffer. - */ -int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen) +/* + Note: we're being called twice. Firstly the client only want the size of all + EA names, secondly it wants these names. In order to avoid scanning EAs twice + we cache them in a static buffer. +*/ +int afp_listextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { - int count, ret, oflag = 0; - uint16_t vid, bitmap; - uint32_t did, maxreply; + int ret, oflag = 0, adflags = 0; + uint16_t vid, bitmap, uint16; + uint32_t did, maxreply, tmpattr; struct vol *vol; struct dir *dir; struct path *s_path; + struct stat *st; struct adouble ad, *adp = NULL; - struct ofork *of; char *uname, *FinderInfo; - static int buf_valid = 0, attrbuflen = 0; + char emptyFinderInfo[32] = { 0 }; -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_listextattr: BEGIN"); -#endif + static int buf_valid = 0; + static size_t attrbuflen = 0; *rbuflen = 0; ibuf += 2; - /* Get MaxReplySize first */ - memcpy( &maxreply, ibuf + 14, 4); + /* Get Bitmap and MaxReplySize first */ + memcpy( &bitmap, ibuf +6, sizeof(bitmap)); + bitmap = ntohs( bitmap ); + + memcpy( &maxreply, ibuf + 14, sizeof (maxreply)); maxreply = ntohl( maxreply ); /* @@ -286,52 +105,57 @@ int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *r attrbuflen = 0; - memcpy( &vid, ibuf, 2); - ibuf += 2; + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); if (NULL == ( vol = getvolbyvid( vid )) ) { - LOG(log_error, logtype_afpd, "afp_listextattr: getvolbyvid error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_listextattr: getvolbyvid error: %s", strerror(errno)); return AFPERR_ACCESS; } - memcpy( &did, ibuf, 4); - ibuf += 4; + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); if (NULL == ( dir = dirlookup( vol, did )) ) { - LOG(log_error, logtype_afpd, "afp_listextattr: dirlookup error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_listextattr: dirlookup error: %s", strerror(errno)); return afp_errno; } - memcpy( &bitmap, ibuf, 2); - bitmap = ntohs( bitmap ); - ibuf += 2; - - if (bitmap & kXAttrNoFollow) - oflag = O_NOFOLLOW; - - /* Skip ReqCount, StartIndex and maxreply*/ - ibuf += 10; + if (bitmap & kXAttrNoFollow) + oflag = O_NOFOLLOW; + /* Skip Bitmap, ReqCount, StartIndex and maxreply*/ + ibuf += 12; /* get name */ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { - LOG(log_error, logtype_afpd, "afp_listextattr: cname error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_listextattr: cname error: %s", strerror(errno)); return AFPERR_NOOBJ; } - uname = s_path->u_name; + st = &s_path->st; + if (!s_path->st_valid) { + /* it's a dir in our cache, we didn't stat it, do it now */ + of_statdir(vol, s_path); + } + if ( s_path->st_errno != 0 ) { + return( AFPERR_NOOBJ ); + } + + adp = of_ad(vol, s_path, &ad); + uname = s_path->u_name; /* We have to check the FinderInfo for the file, because if they aren't all 0 we must return the synthetic attribute "com.apple.FinderInfo". Note: the client will never (never seen in traces) request that attribute via FPGetExtAttr ! */ - if ((of = of_findname(s_path))) { - adp = of->of_ad; - } else { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - adp = &ad; - } - if ( ad_metadata( uname, 0, adp) < 0 ) { + if (S_ISDIR(st->st_mode)) + adflags = ADFLAGS_DIR; + + if ( ad_metadata( uname, adflags, adp) < 0 ) { switch (errno) { + case ENOENT: + adp = NULL; + break; case EACCES: LOG(log_error, logtype_afpd, "afp_listextattr(%s): %s: check resource fork permission?", uname, strerror(errno)); @@ -342,59 +166,66 @@ int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *r } } - FinderInfo = ad_entry(adp, ADEID_FINDERI); + if (adp) { + FinderInfo = ad_entry(adp, ADEID_FINDERI); + #ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_listextattr(%s): FinderInfo:", uname); - hexdump( FinderInfo, 32); + LOG(log_maxdebug, logtype_afpd, "afp_listextattr(%s): FinderInfo:", uname); + hexdump( FinderInfo, 32); #endif - /* Now scan FinderInfo if its all 0 */ - count = 32; - while (count--) { - if (*FinderInfo++) { + if ((adflags & ADFLAGS_DIR)) { + /* set default view */ + uint16 = htons(FINDERINFO_CLOSEDVIEW); + memcpy(emptyFinderInfo + FINDERINFO_FRVIEWOFF, &uint16, 2); + } + + /* Check if FinderInfo equals default and empty FinderInfo*/ + if (memcmp(FinderInfo, emptyFinderInfo, 32) != 0) { /* FinderInfo contains some non 0 bytes -> include "com.apple.FinderInfo" */ strcpy(attrnamebuf, ea_finderinfo); attrbuflen += strlen(ea_finderinfo) + 1; LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): sending com.apple.FinderInfo", uname); - break; } - } - /* Now check for Ressource fork and add virtual EA "com.apple.ResourceFork" if size > 0 */ - LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): Ressourcefork size: %u", uname, adp->ad_eid[ADEID_RFORK].ade_len); - if (adp->ad_eid[ADEID_RFORK].ade_len > 0) { - LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): sending com.apple.RessourceFork.", uname); - strcpy(attrnamebuf + attrbuflen, ea_resourcefork); - attrbuflen += strlen(ea_resourcefork) + 1; - } - - ret = list_extattr(obj, attrnamebuf, &attrbuflen, uname, oflag); - switch (ret) { - case AFPERR_BADTYPE: - /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "afp_listextattr(%s): encountered symlink with kXAttrNoFollow", uname); - attrbuflen = 0; - buf_valid = 0; - ret = AFP_OK; - goto exit; - case AFPERR_MISC: - attrbuflen = 0; - goto exit; - default: - buf_valid = 1; - } + /* Now check for Ressource fork and add virtual EA "com.apple.ResourceFork" if size > 0 */ + LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): Ressourcefork size: %llu", uname, adp->ad_rlen); + + if (adp->ad_rlen > 0) { + LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): sending com.apple.RessourceFork.", uname); + strcpy(attrnamebuf + attrbuflen, ea_resourcefork); + attrbuflen += strlen(ea_resourcefork) + 1; + } + } + + ret = vol->vfs->vfs_ea_list(vol, attrnamebuf, &attrbuflen, uname, oflag); + + switch (ret) { + case AFPERR_BADTYPE: + /* its a symlink and client requested O_NOFOLLOW */ + LOG(log_debug, logtype_afpd, "afp_listextattr(%s): encountered symlink with kXAttrNoFollow", uname); + attrbuflen = 0; + buf_valid = 0; + ret = AFP_OK; + goto exit; + case AFPERR_MISC: + attrbuflen = 0; + goto exit; + default: + buf_valid = 1; + } } /* Start building reply packet */ bitmap = htons(bitmap); - memcpy( rbuf, &bitmap, 2); - rbuf += 2; - *rbuflen += 2; + memcpy( rbuf, &bitmap, sizeof(bitmap)); + rbuf += sizeof(bitmap); + *rbuflen += sizeof(bitmap); - attrbuflen = htonl(attrbuflen); - memcpy( rbuf, &attrbuflen, 4); - rbuf += 4; - *rbuflen += 4; + tmpattr = htonl(attrbuflen); + memcpy( rbuf, &tmpattr, sizeof(tmpattr)); + rbuf += sizeof(tmpattr); + *rbuflen += sizeof(tmpattr); /* Only copy buffer if the client asked for it (2nd request, maxreply>0) and we didnt have an error (buf_valid) */ @@ -408,63 +239,72 @@ int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *r exit: if (ret != AFP_OK) - buf_valid = 0; + buf_valid = 0; if (adp) ad_close_metadata( adp); - LOG(log_debug9, logtype_afpd, "afp_listextattr: END"); return ret; } -int afp_getextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen) +static char *to_stringz(char *ibuf, uint16_t len) +{ +static char attrmname[256]; + + if (len > 255) + /* dont fool with us */ + len = 255; + + /* we must copy the name as its not 0-terminated and I DONT WANT TO WRITE to ibuf */ + strlcpy(attrmname, ibuf, len + 1); + return attrmname; +} + +int afp_getextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { int ret, oflag = 0; - uint16_t vid, bitmap; - uint32_t did, maxreply, attrnamelen; - char attrmname[256], attruname[256]; + uint16_t vid, bitmap, attrnamelen; + uint32_t did, maxreply; + char attruname[256]; struct vol *vol; struct dir *dir; struct path *s_path; -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_getextattr: BEGIN"); -#endif - *rbuflen = 0; ibuf += 2; - memcpy( &vid, ibuf, 2); - ibuf += 2; + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); if (NULL == ( vol = getvolbyvid( vid )) ) { - LOG(log_error, logtype_afpd, "afp_getextattr: getvolbyvid error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_getextattr: getvolbyvid error: %s", strerror(errno)); return AFPERR_ACCESS; } - memcpy( &did, ibuf, 4); - ibuf += 4; + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); if (NULL == ( dir = dirlookup( vol, did )) ) { - LOG(log_error, logtype_afpd, "afp_getextattr: dirlookup error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_getextattr: dirlookup error: %s", strerror(errno)); return afp_errno; } - memcpy( &bitmap, ibuf, 2); + memcpy( &bitmap, ibuf, sizeof(bitmap)); bitmap = ntohs( bitmap ); - ibuf += 2; + ibuf += sizeof(bitmap); + if (bitmap & kXAttrNoFollow) - oflag = AT_SYMLINK_NOFOLLOW; + oflag = O_NOFOLLOW; /* Skip Offset and ReqCount */ ibuf += 16; /* Get MaxReply */ - memcpy(&maxreply, ibuf, 4); + memcpy(&maxreply, ibuf, sizeof(maxreply)); maxreply = ntohl(maxreply); - ibuf += 4; + ibuf += sizeof(maxreply); /* get name */ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { - LOG(log_error, logtype_afpd, "afp_getextattr: cname error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_getextattr: cname error: %s", strerror(errno)); return AFPERR_NOOBJ; } @@ -472,88 +312,72 @@ int afp_getextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int ibuf++; /* get length of EA name */ - memcpy(&attrnamelen, ibuf, 2); + memcpy(&attrnamelen, ibuf, sizeof(attrnamelen)); attrnamelen = ntohs(attrnamelen); - ibuf += 2; - if (attrnamelen > 255) - /* dont fool with us */ - attrnamelen = 255; - - /* we must copy the name as its not 0-terminated and I DONT WANT TO WRITE to ibuf */ - strncpy(attrmname, ibuf, attrnamelen); - attrmname[attrnamelen] = 0; + ibuf += sizeof(attrnamelen); - LOG(log_debug, logtype_afpd, "afp_getextattr(%s): EA: %s", s_path->u_name, attrmname); + LOG(log_debug, logtype_afpd, "afp_getextattr(%s): EA: %s", s_path->u_name, to_stringz(ibuf, attrnamelen)); /* Convert EA name in utf8 to unix charset */ - if ( 0 >= ( attrnamelen = convert_string(CH_UTF8_MAC, obj->options.unixcharset,attrmname, attrnamelen, attruname, 255)) ) - return AFPERR_MISC; + if ( 0 >= convert_string(CH_UTF8_MAC, obj->options.unixcharset, ibuf, attrnamelen, attruname, 256) ) + return AFPERR_MISC; - if (attrnamelen == 255) - /* convert_string didn't 0-terminate */ - attruname[255] = 0; - /* write bitmap now */ bitmap = htons(bitmap); - memcpy(rbuf, &bitmap, 2); - rbuf += 2; - *rbuflen += 2; - + memcpy(rbuf, &bitmap, sizeof(bitmap)); + rbuf += sizeof(bitmap); + *rbuflen += sizeof(bitmap); + /* Switch on maxreply: if its 0 we must return the size of the requested attribute, if its non 0 we must return the attribute. */ if (maxreply == 0) - ret = getextattr_size(rbuf, rbuflen, s_path->u_name, oflag, attruname); + ret = vol->vfs->vfs_ea_getsize(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname); else - ret = getextattr_content(rbuf, rbuflen, s_path->u_name, oflag, attruname, maxreply); - -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_getextattr: END"); -#endif + ret = vol->vfs->vfs_ea_getcontent(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname, maxreply); return ret; } -int afp_setextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen) +int afp_setextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { - int len, oflag = O_CREAT | O_WRONLY, attrdirfd; - uint16_t vid, bitmap; - uint32_t did, attrnamelen, attrsize; - char attrmname[256], attruname[256]; + int oflag = 0, ret; + uint16_t vid, bitmap, attrnamelen; + uint32_t did, attrsize; + char attruname[256]; + char *attrmname; struct vol *vol; struct dir *dir; struct path *s_path; -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_setextattr: BEGIN"); -#endif - *rbuflen = 0; ibuf += 2; - memcpy( &vid, ibuf, 2); - ibuf += 2; + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); if (NULL == ( vol = getvolbyvid( vid )) ) { - LOG(log_error, logtype_afpd, "afp_setextattr: getvolbyvid error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_setextattr: getvolbyvid error: %s", strerror(errno)); return AFPERR_ACCESS; } - memcpy( &did, ibuf, 4); - ibuf += 4; + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); if (NULL == ( dir = dirlookup( vol, did )) ) { - LOG(log_error, logtype_afpd, "afp_setextattr: dirlookup error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_setextattr: dirlookup error: %s", strerror(errno)); return afp_errno; } - memcpy( &bitmap, ibuf, 2); + memcpy( &bitmap, ibuf, sizeof(bitmap)); bitmap = ntohs( bitmap ); - ibuf += 2; + ibuf += sizeof(bitmap); + if (bitmap & kXAttrNoFollow) - oflag |= AT_SYMLINK_NOFOLLOW; + oflag |= O_NOFOLLOW; + if (bitmap & kXAttrCreate) - oflag |= O_EXCL; + oflag |= O_CREAT; else if (bitmap & kXAttrReplace) oflag |= O_TRUNC; @@ -562,7 +386,7 @@ int afp_setextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int /* get name */ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { - LOG(log_error, logtype_afpd, "afp_setextattr: cname error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_setextattr: cname error: %s", strerror(errno)); return AFPERR_NOOBJ; } @@ -570,104 +394,70 @@ int afp_setextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int ibuf++; /* get length of EA name */ - memcpy(&attrnamelen, ibuf, 2); + memcpy(&attrnamelen, ibuf, sizeof(attrnamelen)); attrnamelen = ntohs(attrnamelen); - ibuf += 2; + ibuf += sizeof(attrnamelen); if (attrnamelen > 255) - return AFPERR_PARAM; - - /* we must copy the name as its not 0-terminated and we cant write to ibuf */ - strncpy(attrmname, ibuf, attrnamelen); - attrmname[attrnamelen] = 0; - ibuf += attrnamelen; + return AFPERR_PARAM; + attrmname = ibuf; /* Convert EA name in utf8 to unix charset */ - if ( 0 >= ( attrnamelen = convert_string(CH_UTF8_MAC, obj->options.unixcharset,attrmname, attrnamelen, attruname, 255)) ) - return AFPERR_MISC; - - if (attrnamelen == 255) - /* convert_string didn't 0-terminate */ - attruname[255] = 0; + if ( 0 >= convert_string(CH_UTF8_MAC, obj->options.unixcharset, attrmname, attrnamelen, attruname, 256)) + return AFPERR_MISC; + ibuf += attrnamelen; /* get EA size */ - memcpy(&attrsize, ibuf, 4); + memcpy(&attrsize, ibuf, sizeof(attrsize)); attrsize = ntohl(attrsize); - ibuf += 4; + ibuf += sizeof(attrsize); if (attrsize > MAX_EA_SIZE) - /* we arbitrarily make this fatal */ - return AFPERR_PARAM; - - LOG(log_debug, logtype_afpd, "afp_setextattr(%s): EA: %s, size: %u", s_path->u_name, attrmname, attrsize); - - if ( -1 == (attrdirfd = attropen(s_path->u_name, attruname, oflag, 0666))) { - if (errno == ELOOP) { - /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "afp_setextattr(%s): encountered symlink with kXAttrNoFollow", s_path->u_name); - return AFP_OK; - } - LOG(log_error, logtype_afpd, "afp_setextattr(%s): attropen error: %s", s_path->u_name, strerror(errno)); - return AFPERR_MISC; - } - - while (1) { - len = write(attrdirfd, ibuf, attrsize); - if (len == -1) { - LOG(log_error, logtype_afpd, "afp_setextattr(%s): read error: %s", attruname, strerror(errno)); - return AFPERR_MISC; - } - attrsize -= len; - ibuf += len; - if (attrsize == 0) - break; - } + /* we arbitrarily make this fatal */ + return AFPERR_PARAM; -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_setextattr: END"); -#endif + LOG(log_debug, logtype_afpd, "afp_setextattr(%s): EA: %s, size: %u", s_path->u_name, to_stringz(attrmname, attrnamelen), attrsize); - return AFP_OK; + ret = vol->vfs->vfs_ea_set(vol, s_path->u_name, attruname, ibuf, attrsize, oflag); + + return ret; } -int afp_remextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen) +int afp_remextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { - int oflag = O_RDONLY, attrdirfd; - uint16_t vid, bitmap; - uint32_t did, attrnamelen; - char attrmname[256], attruname[256]; + int oflag = 0, ret; + uint16_t vid, bitmap, attrnamelen; + uint32_t did; + char attruname[256]; struct vol *vol; struct dir *dir; struct path *s_path; -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_remextattr: BEGIN"); -#endif - *rbuflen = 0; ibuf += 2; - memcpy( &vid, ibuf, 2); - ibuf += 2; + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); if (NULL == ( vol = getvolbyvid( vid )) ) { - LOG(log_error, logtype_afpd, "afp_remextattr: getvolbyvid error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_remextattr: getvolbyvid error: %s", strerror(errno)); return AFPERR_ACCESS; } - memcpy( &did, ibuf, 4); - ibuf += 4; + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); if (NULL == ( dir = dirlookup( vol, did )) ) { - LOG(log_error, logtype_afpd, "afp_remextattr: dirlookup error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_remextattr: dirlookup error: %s", strerror(errno)); return afp_errno; } - memcpy( &bitmap, ibuf, 2); + memcpy( &bitmap, ibuf, sizeof(bitmap)); bitmap = ntohs( bitmap ); - ibuf += 2; + ibuf += sizeof(bitmap); + if (bitmap & kXAttrNoFollow) - oflag |= AT_SYMLINK_NOFOLLOW; + oflag |= O_NOFOLLOW; /* get name */ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { - LOG(log_error, logtype_afpd, "afp_setextattr: cname error: %s", strerror(errno)); + LOG(log_debug, logtype_afpd, "afp_setextattr: cname error: %s", strerror(errno)); return AFPERR_NOOBJ; } @@ -675,59 +465,20 @@ int afp_remextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int ibuf++; /* get length of EA name */ - memcpy(&attrnamelen, ibuf, 2); + memcpy(&attrnamelen, ibuf, sizeof(attrnamelen)); attrnamelen = ntohs(attrnamelen); - ibuf += 2; + ibuf += sizeof(attrnamelen); if (attrnamelen > 255) - return AFPERR_PARAM; - - /* we must copy the name as its not 0-terminated and we cant write to ibuf */ - strncpy(attrmname, ibuf, attrnamelen); - attrmname[attrnamelen] = 0; - ibuf += attrnamelen; + return AFPERR_PARAM; /* Convert EA name in utf8 to unix charset */ - if ( 0 >= ( attrnamelen = convert_string(CH_UTF8_MAC, obj->options.unixcharset,attrmname, attrnamelen, attruname, 255)) ) - return AFPERR_MISC; - - if (attrnamelen == 255) - /* convert_string didn't 0-terminate */ - attruname[255] = 0; - - LOG(log_debug, logtype_afpd, "afp_remextattr(%s): EA: %s", s_path->u_name, attrmname); - - if ( -1 == (attrdirfd = attropen(s_path->u_name, ".", oflag))) { - switch (errno) { - case ELOOP: - /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "afp_remextattr(%s): encountered symlink with kXAttrNoFollow", s_path->u_name); - return AFP_OK; - case EACCES: - LOG(log_debug, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", s_path->u_name, strerror(errno)); - return AFPERR_ACCESS; - default: - LOG(log_error, logtype_afpd, "afp_remextattr(%s): attropen error: %s", s_path->u_name, strerror(errno)); - return AFPERR_MISC; - } - } - - if ( -1 == (unlinkat(attrdirfd, attruname, 0)) ) { - if (errno == EACCES) { - LOG(log_debug, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", s_path->u_name, strerror(errno)); - return AFPERR_ACCESS; - } - LOG(log_error, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", s_path->u_name, strerror(errno)); - return AFPERR_MISC; - } - -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_remextattr: END"); -#endif - - return AFP_OK; -} + if ( 0 >= (convert_string(CH_UTF8_MAC, obj->options.unixcharset,ibuf, attrnamelen, attruname, 256)) ) + return AFPERR_MISC; + LOG(log_debug, logtype_afpd, "afp_remextattr(%s): EA: %s", s_path->u_name, to_stringz(ibuf, attrnamelen)); + ret = vol->vfs->vfs_ea_remove(vol, s_path->u_name, attruname, oflag); -#endif /* HAVE_EXT_ATTRS */ + return ret; +}