ssize_t ceph_os_flistxattr(int fd, char *list, size_t size) { ssize_t error = -1; #if defined(__FreeBSD__) /* * XXX. The format of the list FreeBSD returns differs * from the Linux ones. We have to perform the conversion. :-( */ char *newlist, *p, *p1; if (size != 0) { newlist = malloc(size); if (newlist != NULL) { error = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, newlist, size); if (error > 0) { p = newlist; p1 = list; while ((p - newlist) < error) { uint8_t len = *(uint8_t *)p; p++; if ((p + len - newlist) > error) break; if (len > 0) { bcopy(p, p1, len); p += len; p1 += len; *p1++ = '\0'; } } error = p1 - list; } free(newlist); } } else { error = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, list, size); } #elif defined(__linux__) //提取文件的所有属性列表 error = flistxattr(fd, list, size); #elif defined(__APPLE__) error = flistxattr(fd, list, size, 0); #endif return (error); }
static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) { ssize_t list_size; int i, len; switch(type) { #if defined(HAVE_EXTATTR_LIST_FILE) case 0: list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size); break; #endif #if defined(HAVE_EXTATTR_LIST_LINK) case 1: list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size); break; #endif #if defined(HAVE_EXTATTR_LIST_FD) case 2: list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size); break; #endif default: errno = ENOSYS; return -1; } /* Some error happend. Errno should be set by the previous call */ if(list_size < 0) return -1; /* No attributes */ if(list_size == 0) return 0; /* XXX: Call with an empty buffer may be used to calculate necessary buffer size. Unfortunately, we can't say, how many attributes were returned, so here is the potential problem with the emulation. */ if(list == NULL) return list_size; /* Buffer is too small to fit the results */ if(list_size > size) { errno = ERANGE; return -1; } /* Convert from pascal strings to C strings */ len = list[0]; memmove(list, list + 1, list_size); for(i = len; i < list_size; ) { len = list[i]; list[i] = '\0'; i += len + 1; } return list_size; }
static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) { ssize_t rv = 0; if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { return -1; } if (options & XATTR_XATTR_NOFOLLOW) { return -1; } else { rv = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, namebuf, size); } if (rv > 0 && namebuf) { convert_bsd_list(namebuf, rv); } return rv; }
static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) { ssize_t list_size, total_size = 0; int i, t, len; char *buf; /* Iterate through extattr(2) namespaces */ for(t = 0; t < ARRAY_SIZE(extattr); t++) { if (t != EXTATTR_NAMESPACE_USER && geteuid() != 0) { /* ignore all but user namespace when we are not root, see bug 10247 */ continue; } switch(type) { #if defined(HAVE_EXTATTR_LIST_FILE) case 0: list_size = extattr_list_file(arg.path, extattr[t].space, list, size); break; #endif #if defined(HAVE_EXTATTR_LIST_LINK) case 1: list_size = extattr_list_link(arg.path, extattr[t].space, list, size); break; #endif #if defined(HAVE_EXTATTR_LIST_FD) case 2: list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size); break; #endif default: errno = ENOSYS; return -1; } /* Some error happend. Errno should be set by the previous call */ if(list_size < 0) return -1; /* No attributes */ if(list_size == 0) continue; /* XXX: Call with an empty buffer may be used to calculate necessary buffer size. Unfortunately, we can't say, how many attributes were returned, so here is the potential problem with the emulation. */ if(list == NULL) { /* Take the worse case of one char attribute names - two bytes per name plus one more for sanity. */ total_size += list_size + (list_size/2 + 1)*extattr[t].len; continue; } /* Count necessary offset to fit namespace prefixes */ len = 0; for(i = 0; i < list_size; i += list[i] + 1) len += extattr[t].len; total_size += list_size + len; /* Buffer is too small to fit the results */ if(total_size > size) { errno = ERANGE; return -1; } /* Shift results back, so we can prepend prefixes */ buf = (char *)memmove(list + len, list, list_size); for(i = 0; i < list_size; i += len + 1) { len = buf[i]; strncpy(list, extattr[t].name, extattr[t].len + 1); list += extattr[t].len; strncpy(list, buf + i + 1, len); list[len] = '\0'; list += len + 1; } size -= total_size; } return total_size; }