/* store metadata from the curl request alongside the downloaded * file using extended attributes */ int fwrite_xattr(CURL *curl, int fd) { int i = 0; int err = 0; /* loop through all xattr-curlinfo pairs and abort on a set error */ while(err == 0 && mappings[i].attr != NULL) { char *value = NULL; CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value); if(!result && value) { #ifdef HAVE_FSETXATTR_6 err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0); #elif defined(HAVE_FSETXATTR_5) err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0); #elif defined(__FreeBSD_version) err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr, value, strlen(value)); /* FreeBSD's extattr_set_fd returns the length of the extended attribute */ err = err < 0 ? err : 0; #endif } i++; } return err; }
/* * Set attributes on a file descriptor. */ static void set_extattr_fd(int fd, char *name, void *buf, int size) { struct extattr *eap, *eaend; vprintf(stdout, "Set attributes for %s:", name); eaend = buf + size; for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) { /* * Make sure this entry is complete. */ if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) { dprintf(stdout, "\n\t%scorrupted", eap == buf ? "" : "remainder "); break; } if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY) continue; vprintf(stdout, "\n\t%s, (%d bytes), %*s", namespace_names[eap->ea_namespace], eap->ea_length, eap->ea_namelength, eap->ea_name); /* * First we try the general attribute setting interface. * However, some attributes can only be set by root or * by using special interfaces (for example, ACLs). */ if (extattr_set_fd(fd, eap->ea_namespace, eap->ea_name, EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) { dprintf(stdout, " (set using extattr_set_fd)"); continue; } /* * If the general interface refuses to set the attribute, * then we try all the specialized interfaces that we * know about. */ if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) { if (acl_set_fd(fd, EXTATTR_CONTENT(eap)) != -1) { dprintf(stdout, " (set using acl_set_fd)"); continue; } } if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) { if (acl_set_file(name, ACL_TYPE_DEFAULT, EXTATTR_CONTENT(eap)) != -1) { dprintf(stdout, " (set using acl_set_file)"); continue; } } vprintf(stdout, " (unable to set)"); } vprintf(stdout, "\n"); }
int ceph_os_fsetxattr(int fd, const char *name, const void *value, size_t size) { int error = -1; #if defined(__FreeBSD__) error = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size); if (error > 0) error = 0; #elif defined(__linux__) || defined(DARWIN) error = fsetxattr(fd, name, value, size, 0); #endif return (error); }
int ceph_os_fsetxattr(int fd, const char *name, const void *value, size_t size) { int error = -1; #if defined(__FreeBSD__) error = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size); if (error > 0) error = 0; #elif defined(__linux__) error = fsetxattr(fd, name, value, size, 0); #elif defined(__APPLE__) error = fsetxattr(fd, name, value, size, 0, 0 /* no options should be identical to Linux */ ); #endif return (error); }
static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, ssize_t size, u_int32_t position, int options) { int rv = 0; int nofollow; if (position != 0) { return -1; } nofollow = options & XATTR_XATTR_NOFOLLOW; options &= ~XATTR_XATTR_NOFOLLOW; if (options == XATTR_XATTR_CREATE || options == XATTR_XATTR_REPLACE) { /* freebsd noop */ } else if (options != 0) { return -1; } if (nofollow) { return -1; } else { rv = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size); } /* freebsd returns the written length on success, not zero. */ if (rv >= 0) { return 0; } else { return rv; } }
int sys_fsetxattr (int filedes, const char *uname, const void *value, size_t size, int flags) { const char *name = prefix(uname); #if defined(HAVE_FSETXATTR) #ifndef XATTR_ADD_OPT return fsetxattr(filedes, name, value, size, flags); #else int options = 0; return fsetxattr(filedes, name, value, size, 0, options); #endif #elif defined(HAVE_FSETEA) return fsetea(filedes, name, value, size, flags); #elif defined(HAVE_EXTATTR_SET_FD) char *s; int retval = 0; int attrnamespace = (strncmp(name, "system", 6) == 0) ? EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1; if (flags) { /* Check attribute existence */ retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0); if (retval < 0) { /* REPLACE attribute, that doesn't exist */ if (flags & XATTR_REPLACE && errno == ENOATTR) { errno = ENOATTR; return -1; } /* Ignore other errors */ } else { if (flags & XATTR_CREATE) { errno = EEXIST; return -1; } } } retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size); return (retval < 0) ? -1 : 0; #elif defined(HAVE_ATTR_SETF) int myflags = 0; char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; return attr_setf(filedes, attrname, (const char *)value, size, myflags); #elif defined(HAVE_ATTROPEN) int ret = -1; int myflags = O_RDWR | O_XATTR; int attrfd; if (flags & XATTR_CREATE) myflags |= O_EXCL; if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); if (attrfd >= 0) { ret = solaris_write_xattr(attrfd, value, size); close(attrfd); } return ret; #else errno = ENOSYS; return -1; #endif }