From: Richard D. <ric...@us...> - 2006-10-01 11:18:56
|
Update of /cvsroot/file-extattr/File-ExtAttr In directory sc8-pr-cvs5.sourceforge.net:/tmp/cvs-serv9280 Modified Files: ExtAttr.xs extattr_linux.c extattr_linux.h portable.h Log Message: First cut of namespace list function for Linux Index: portable.h =================================================================== RCS file: /cvsroot/file-extattr/File-ExtAttr/portable.h,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** portable.h 1 Oct 2006 08:18:49 -0000 1.11 --- portable.h 1 Oct 2006 11:18:54 -0000 1.12 *************** *** 166,168 **** --- 166,202 ---- } + static inline int + portable_listxattrns(const char *path, + char *buf, + const size_t slen, + struct hv *flags) + { + #ifdef EXTATTR_MACOSX + return macosx_listxattrns(path, buf, slen, flags); + #elif defined(EXTATTR_BSD) + return bsd_listxattrns(path, buf, slen, flags); + #elif defined(EXTATTR_SOLARIS) + return solaris_listxattrns(path, buf, slen, flags); + #else + return linux_listxattrns(path, buf, slen, flags); + #endif + } + + static inline int + portable_flistxattrns(const int fd, + char *buf, + const size_t slen, + struct hv *flags) + { + #ifdef EXTATTR_MACOSX + return macosx_flistxattrns(fd, buf, slen, flags); + #elif defined(EXTATTR_BSD) + return bsd_flistxattrns(fd, buf, slen, flags); + #elif defined(EXTATTR_SOLARIS) + return solaris_flistxattrns(fd, buf, slen, flags); + #else + return linux_flistxattrns(fd, buf, slen, flags); + #endif + } + #endif /* EXTATTR_PORTABLE_H */ Index: extattr_linux.h =================================================================== RCS file: /cvsroot/file-extattr/File-ExtAttr/extattr_linux.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** extattr_linux.h 19 Aug 2006 14:06:22 -0000 1.2 --- extattr_linux.h 1 Oct 2006 11:18:54 -0000 1.3 *************** *** 50,52 **** --- 50,62 ---- struct hv *flags); + ssize_t linux_listxattrns (const char *path, + char *buf, + const size_t buflen, + struct hv *flags); + + ssize_t linux_flistxattrns (const int fd, + char *buf, + const size_t buflen, + struct hv *flags); + #endif /* EXTATTR_LINUX_H */ Index: ExtAttr.xs =================================================================== RCS file: /cvsroot/file-extattr/File-ExtAttr/ExtAttr.xs,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** ExtAttr.xs 19 Aug 2006 18:34:42 -0000 1.19 --- ExtAttr.xs 1 Oct 2006 11:18:54 -0000 1.20 *************** *** 227,228 **** --- 227,290 ---- free(namebuf); + + void + _listfattrns (path, fd, flags = 0) + const char *path + int fd + HV * flags + PREINIT: + ssize_t size, ret; + char *namebuf = NULL; + char *nameptr; + + PPCODE: + if(fd == -1) + size = portable_listxattrns(path, NULL, 0, flags); + else + size = portable_flistxattrns(fd, NULL, 0, flags); + + if (size == -1) + { + XSRETURN_UNDEF; + } else if (size == 0) + { + XSRETURN_EMPTY; + } + + namebuf = malloc(size); + + if (fd == -1) + ret = portable_listxattrns(path, namebuf, size, flags); + else + ret = portable_flistxattrns(fd, namebuf, size, flags); + + // There could be a race condition here, if someone adds a new + // attribute between the two listxattr calls. However it just means we + // might return ERANGE. + + if (ret == -1) + { + free(namebuf); + XSRETURN_UNDEF; + } else if (ret == 0) + { + free(namebuf); + XSRETURN_EMPTY; + } + + nameptr = namebuf; + + while(nameptr < namebuf + ret) + { + char *endptr = nameptr; + while(*endptr++ != '\0'); + + // endptr will now point one past the end.. + + XPUSHs(sv_2mortal(newSVpvn(nameptr, endptr - nameptr - 1))); + + // nameptr could now point past the end of namebuf + nameptr = endptr; + } + + free(namebuf); Index: extattr_linux.c =================================================================== RCS file: /cvsroot/file-extattr/File-ExtAttr/extattr_linux.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** extattr_linux.c 1 Oct 2006 08:21:52 -0000 1.4 --- extattr_linux.c 1 Oct 2006 11:18:54 -0000 1.5 *************** *** 9,17 **** #include "flags.h" ! static const char NAMESPACE_DEFAULT[] = "user"; static char * flags2namespace (struct hv *flags) { const size_t NAMESPACE_KEYLEN = strlen(NAMESPACE_KEY); SV **psv_ns; --- 9,48 ---- #include "flags.h" ! static void * ! memstr (void *buf, const char *str, const size_t buflen) ! { ! void *p = buf; ! size_t len = buflen; ! const size_t slen = strlen(str); ! ! /* Ignore empty strings and buffers. */ ! if ((slen == 0) || (buflen == 0)) ! p = NULL; ! ! while (p && (len >= slen)) ! { ! /* ! * Find the first character of the string, then see if the rest ! * matches. ! */ ! p = memchr(p, str[0], len); ! if (!p) ! break; ! ! if (memcmp(p, str, slen) == 0) ! break; ! ! /* Next! */ ! ++p; ! --len; ! } ! ! return p; ! } static char * flags2namespace (struct hv *flags) { + static const char NAMESPACE_DEFAULT[] = "user"; const size_t NAMESPACE_KEYLEN = strlen(NAMESPACE_KEY); SV **psv_ns; *************** *** 269,271 **** --- 300,437 ---- } + static ssize_t + attrlist2nslist (char *sbuf, const size_t slen, char *buf, const size_t buflen) + { + ssize_t sbuiltlen = 0; + ssize_t spos = 0; + int ret = -1; + + for (spos = 0; (spos < slen); ) + { + char *pns, *pval; + + /* Get the namespace. */ + pns = &sbuf[spos]; + pval = strchr(pns, '.'); + if (!pval) + break; + + /* Point spos at the next attribute. */ + spos += strlen(pval) + 1; + + /* Check we haven't already seen this namespace. */ + *pval = '\0'; + ++pval; + if (memstr(sbuf, pns, sbuiltlen) != NULL) + continue; + + /* + * We build the results in sbuf. So sbuf will contain the list + * returned by listxattr and the list of namespaces. + * We shift the namespaces from the list to the start of the buffer. + */ + memmove(&sbuf[sbuiltlen], pns, strlen(pns) + 1 /* nul */); + sbuiltlen += strlen(pns) + 1; + } + + if (buflen == 0) + { + /* Return what space is required. */ + ret = sbuiltlen; + } + else if (sbuiltlen <= buflen) + { + memcpy(buf, sbuf, sbuiltlen); + ret = sbuiltlen; + } + else + { + errno = ERANGE; + ret = -1; + } + + return ret; + } + + /* XXX: Just return a Perl list? */ + ssize_t + linux_listxattrns (const char *path, + char *buf, + const size_t buflen, + struct hv *flags) + { + ssize_t slen; + ssize_t ret; + + /* + * Get a buffer of nul-delimited "namespace.attribute"s, + * then extract the namespaces into buf. + */ + slen = listxattr(path, buf, 0); + if (slen >= 0) + { + char *sbuf; + + sbuf = malloc(slen); + if (sbuf) + slen = listxattr(path, sbuf, slen); + else + ret = -1; + + if (slen) + ret = attrlist2nslist(sbuf, slen, buf, buflen); + else + ret = slen; + + if (sbuf) + free(sbuf); + } + else + { + ret = slen; + } + + return ret; + } + + ssize_t + linux_flistxattrns (const int fd, + char *buf, + const size_t buflen, + struct hv *flags) + { + ssize_t slen; + ssize_t ret; + + /* + * Get a buffer of nul-delimited "namespace.attribute"s, + * then extract the namespaces into buf. + */ + slen = flistxattr(fd, buf, 0); + if (slen >= 0) + { + char *sbuf; + + sbuf = malloc(slen); + if (sbuf) + slen = flistxattr(fd, sbuf, slen); + else + ret = -1; + + if (slen) + ret = attrlist2nslist(sbuf, slen, buf, buflen); + else + ret = slen; + + if (sbuf) + free(sbuf); + } + else + { + ret = slen; + } + + return ret; + } + #endif /* EXTATTR_LINUX */ |