X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fextattrs.c;h=4cbeb6423ddd316cb28dc32cec5488ce98ed0f81;hb=edf01c724768d494e522ec84380e8e49b37a2bd6;hp=2900be3d2b7ab91da36d846fbb28069b685ef198;hpb=9f013bf0ce828ff7c61db4f5a404d9029ed82999;p=netatalk.git diff --git a/etc/afpd/extattrs.c b/etc/afpd/extattrs.c index 2900be3d..4cbeb642 100644 --- a/etc/afpd/extattrs.c +++ b/etc/afpd/extattrs.c @@ -1,5 +1,4 @@ /* - $Id: extattrs.c,v 1.5 2009-10-14 15:04:00 franklahm Exp $ Copyright (c) 2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@ -21,30 +20,29 @@ #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 */ static char attrnamebuf[ATTRNAMEBUFSIZ]; +#ifdef DEBUG static void hexdump(void *m, size_t l) { char *p = m; int count = 0, len; @@ -62,6 +60,7 @@ static void hexdump(void *m, size_t l) { } } } +#endif /*************************************** * AFP funcs @@ -72,24 +71,30 @@ static void hexdump(void *m, size_t l) { 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) +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; + 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 }; + + 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 ); /* @@ -100,53 +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; - -#ifdef HAVE_SOLARIS_EAS if (bitmap & kXAttrNoFollow) oflag = O_NOFOLLOW; -#endif - /* Skip ReqCount, StartIndex and maxreply*/ - ibuf += 10; + /* 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 ); + } + + 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; + + adp = &ad; + ad_init(adp, vol); + if (ad_metadata(uname, adflags, adp) != 0 ) { switch (errno) { + case ENOENT: + break; case EACCES: LOG(log_error, logtype_afpd, "afp_listextattr(%s): %s: check resource fork permission?", uname, strerror(errno)); @@ -155,34 +164,33 @@ int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *r LOG(log_error, logtype_afpd, "afp_listextattr(%s): error getting metadata: %s", uname, strerror(errno)); return AFPERR_MISC; } - } + } else { + FinderInfo = ad_entry(adp, ADEID_FINDERI); - FinderInfo = ad_entry(adp, ADEID_FINDERI); -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "afp_listextattr(%s): FinderInfo:", uname); - hexdump( FinderInfo, 32); -#endif + if ((adflags & ADFLAGS_DIR)) { + /* set default view */ + uint16 = htons(FINDERINFO_CLOSEDVIEW); + memcpy(emptyFinderInfo + FINDERINFO_FRVIEWOFF, &uint16, 2); + } - /* Now scan FinderInfo if its all 0 */ - count = 32; - while (count--) { - if (*FinderInfo++) { + /* 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; - } + /* 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) { @@ -199,18 +207,18 @@ int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *r default: buf_valid = 1; } - } + } /* if ((maxreply == 0) || (buf_valid == 0)) */ /* 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); tmpattr = htonl(attrbuflen); - memcpy( rbuf, &tmpattr, 4); - rbuf += 4; - *rbuflen += 4; + 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) */ @@ -225,18 +233,32 @@ int afp_listextattr(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *r exit: if (ret != AFP_OK) buf_valid = 0; + if (adp) - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); 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; @@ -245,40 +267,38 @@ int afp_getextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *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); -#ifdef HAVE_SOLARIS_EAS if (bitmap & kXAttrNoFollow) oflag = O_NOFOLLOW; -#endif /* 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; } @@ -286,32 +306,21 @@ 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; + ibuf += sizeof(attrnamelen); - /* 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; - - 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)) ) + 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: @@ -326,12 +335,13 @@ int afp_getextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int 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 oflag = O_CREAT | O_WRONLY, ret; - 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; @@ -339,31 +349,29 @@ int afp_setextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *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); -#ifdef HAVE_SOLARIS_EAS if (bitmap & kXAttrNoFollow) - oflag |= AT_SYMLINK_NOFOLLOW; -#endif + oflag |= O_NOFOLLOW; if (bitmap & kXAttrCreate) - oflag |= O_EXCL; + oflag |= O_CREAT; else if (bitmap & kXAttrReplace) oflag |= O_TRUNC; @@ -372,7 +380,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; } @@ -380,46 +388,39 @@ 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; - + 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)) ) + if ( 0 >= convert_string(CH_UTF8_MAC, obj->options.unixcharset, attrmname, attrnamelen, attruname, 256)) return AFPERR_MISC; - if (attrnamelen == 255) - /* convert_string didn't 0-terminate */ - attruname[255] = 0; - + 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); + LOG(log_debug, logtype_afpd, "afp_setextattr(%s): EA: %s, size: %u", s_path->u_name, to_stringz(attrmname, attrnamelen), attrsize); 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, ret; - 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; @@ -427,32 +428,30 @@ int afp_remextattr(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *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); -#ifdef HAVE_SOLARIS_EAS if (bitmap & kXAttrNoFollow) - oflag |= AT_SYMLINK_NOFOLLOW; -#endif + 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; } @@ -460,26 +459,17 @@ 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; - /* Convert EA name in utf8 to unix charset */ - if ( 0 >= ( attrnamelen = convert_string(CH_UTF8_MAC, obj->options.unixcharset,attrmname, attrnamelen, attruname, 255)) ) + 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; - - LOG(log_debug, logtype_afpd, "afp_remextattr(%s): EA: %s", s_path->u_name, attrmname); + 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);