/* * Function: sys_get_eacontent * * Purpose: copy native EA into rbuf * * Arguments: * * vol (r) current volume * rbuf (w) DSI reply buffer * rbuflen (rw) current length of data in reply buffer * uname (r) filename * oflag (r) link and create flag * attruname (r) name of attribute * maxreply (r) maximum EA size as of current specs/real-life * fd (r) file descriptor * Returns: AFP code: AFP_OK on success or appropiate AFP error code * * Effects: * * Copies EA into rbuf. Increments *rbuflen accordingly. */ int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) { ssize_t ret; uint32_t attrsize; /* Start building reply packet */ maxreply -= MAX_REPLY_EXTRA_BYTES; if (maxreply > MAX_EA_SIZE) maxreply = MAX_EA_SIZE; LOG(log_debug7, logtype_afpd, "sys_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply); if (vol->v_flags & AFPVOL_EA_SAMBA) { maxreply++; } /* PBaranski fix */ if (fd != -1) { LOG(log_debug, logtype_afpd, "sys_get_eacontent(%s): file is already opened", uname); ret = sys_fgetxattr(fd, attruname, rbuf +4, maxreply); } else { if ((oflag & O_NOFOLLOW) ) { ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply); } else { ret = sys_getxattr(uname, attruname, rbuf +4, maxreply); } } /* PBaranski fix */ if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): symlink with kXAttrNoFollow", uname); return AFPERR_MISC; case ENOATTR: if (vol->v_obj->afp_version >= 34) return AFPERR_NOITEM; return AFPERR_MISC; default: LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno)); return AFPERR_MISC; } } if (vol->v_flags & AFPVOL_EA_SAMBA) { /* What can we do about xattrs that are 1 byte large? */ if (ret < 2) { memset(rbuf, 0, 4); *rbuflen += 4; if (vol->v_obj->afp_version >= 34) { return AFPERR_NOITEM; } return AFPERR_MISC; } ret--; } /* remember where we must store length of attribute data in rbuf */ *rbuflen += 4 +ret; attrsize = htonl((uint32_t)ret); memcpy(rbuf, &attrsize, 4); return AFP_OK; }
/* * Function: sys_get_easize * * Purpose: get size of a native EA * * Arguments: * * vol (r) current volume * rbuf (w) DSI reply buffer * rbuflen (rw) current length of data in reply buffer * uname (r) filename * oflag (r) link and create flag * attruname (r) name of attribute * * Returns: AFP code: AFP_OK on success or appropiate AFP error code * * Effects: * * Copies EA size into rbuf in network order. Increments *rbuflen +4. */ int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE) { ssize_t ret; uint32_t attrsize; LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\"", uname, attruname); /* PBaranski fix */ if (fd != -1) { LOG(log_debug, logtype_afpd, "sys_get_easize(%s): file is already opened", uname); ret = sys_fgetxattr(fd, attruname, rbuf +4, 0); } else { if ((oflag & O_NOFOLLOW) ) { ret = sys_lgetxattr(uname, attruname, rbuf +4, 0); } else { ret = sys_getxattr(uname, attruname, rbuf +4, 0); } } /* PBaranski fix */ if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): symlink with kXAttrNoFollow", uname); return AFPERR_MISC; case ENOATTR: case ENOENT: if (vol->v_obj->afp_version >= 34) return AFPERR_NOITEM; return AFPERR_MISC; default: LOG(log_debug, logtype_afpd, "sys_getextattr_size: error: %s", strerror(errno)); return AFPERR_MISC; } } if (ret > MAX_EA_SIZE) ret = MAX_EA_SIZE; if (vol->v_flags & AFPVOL_EA_SAMBA) { /* What can we do about xattrs that are 1 byte large? */ if (ret < 2) { memset(rbuf, 0, 4); *rbuflen += 4; if (vol->v_obj->afp_version >= 34) { return AFPERR_NOITEM; } return AFPERR_MISC; } ret--; } /* Start building reply packet */ LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, ret); /* length of attribute data */ attrsize = htonl((uint32_t)ret); memcpy(rbuf, &attrsize, 4); *rbuflen += 4; ret = AFP_OK; return ret; }
ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) { return sys_fgetxattr(fd, name, value, size); }