aboutsummaryrefslogtreecommitdiff
path: root/sys/sys/extattr.h
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2007-02-26 06:18:53 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2007-02-26 06:18:53 +0000
commitfdece2b8f73a053931da1593a869c2eb6437bddd (patch)
treea9b374203a4a0935735ed723d29c64680d40d3e7 /sys/sys/extattr.h
parent82003b276a8d64415ecd1e83f013085129edf9d8 (diff)
downloadsrc-fdece2b8f73a053931da1593a869c2eb6437bddd.tar.gz
src-fdece2b8f73a053931da1593a869c2eb6437bddd.zip
Declare a `struct extattr' that defines the format of an extended
attribute. Also define some macros to manipulate one of these structures. Explain their use in the extattr.9 manual page. The next step will be to make a sweep through the kernel replacing the old pointer manipulation code. To get an idea of how they would be used, the ffs_findextattr() function in ufs/ffs/ffs_vnops.c is currently written as follows: /* * Vnode operating to retrieve a named extended attribute. * * Locate a particular EA (nspace:name) in the area (ptr:length), and return * the length of the EA, and possibly the pointer to the entry and to the data. */ static int ffs_findextattr(u_char *ptr, u_int length, int nspace, const char *name, u_char **eap, u_char **eac) { u_char *p, *pe, *pn, *p0; int eapad1, eapad2, ealength, ealen, nlen; uint32_t ul; pe = ptr + length; nlen = strlen(name); for (p = ptr; p < pe; p = pn) { p0 = p; bcopy(p, &ul, sizeof(ul)); pn = p + ul; /* make sure this entry is complete */ if (pn > pe) break; p += sizeof(uint32_t); if (*p != nspace) continue; p++; eapad2 = *p++; if (*p != nlen) continue; p++; if (bcmp(p, name, nlen)) continue; ealength = sizeof(uint32_t) + 3 + nlen; eapad1 = 8 - (ealength % 8); if (eapad1 == 8) eapad1 = 0; ealength += eapad1; ealen = ul - ealength - eapad2; p += nlen + eapad1; if (eap != NULL) *eap = p0; if (eac != NULL) *eac = p; return (ealen); } return(-1); } After applying the structure and macros, it would look like this: /* * Vnode operating to retrieve a named extended attribute. * * Locate a particular EA (nspace:name) in the area (ptr:length), and return * the length of the EA, and possibly the pointer to the entry and to the data. */ static int ffs_findextattr(u_char *ptr, u_int length, int nspace, const char *name, u_char **eapp, u_char **eac) { struct extattr *eap, *eaend; eaend = (struct extattr *)(ptr + length); for (eap = (struct extattr *)ptr; eap < eaend; eap = EXTATTR_NEXT(eap)){ /* make sure this entry is complete */ if (EXTATTR_NEXT(eap) > eaend) break; if (eap->ea_namespace != nspace || eap->ea_namelength != length || bcmp(eap->ea_name, name, length)) continue; if (eapp != NULL) *eapp = eap; if (eac != NULL) *eac = EXTATTR_CONTENT(eap); return (EXTATTR_CONTENT_SIZE(eap)); } return(-1); } Not only is it considerably shorter, but it hopefully more readable :-)
Notes
Notes: svn path=/head/; revision=167010
Diffstat (limited to 'sys/sys/extattr.h')
-rw-r--r--sys/sys/extattr.h59
1 files changed, 59 insertions, 0 deletions
diff --git a/sys/sys/extattr.h b/sys/sys/extattr.h
index 0d9429d3daf1..b531e7ee6e2c 100644
--- a/sys/sys/extattr.h
+++ b/sys/sys/extattr.h
@@ -39,11 +39,65 @@
* Defined name spaces for extended attributes. Numeric constants are passed
* via system calls, but a user-friendly string is also defined.
*/
+#define EXTATTR_NAMESPACE_EMPTY 0x00000000
+#define EXTATTR_NAMESPACE_EMPTY_STRING "empty"
#define EXTATTR_NAMESPACE_USER 0x00000001
#define EXTATTR_NAMESPACE_USER_STRING "user"
#define EXTATTR_NAMESPACE_SYSTEM 0x00000002
#define EXTATTR_NAMESPACE_SYSTEM_STRING "system"
+/*
+ * The following macro is designed to initialize an array that maps
+ * extended-attribute namespace values to their names, e.g.,
+ * char *extattr_namespace_names[] = EXTATTR_NAMESPACE_NAMES;
+ */
+#define EXTATTR_NAMESPACE_NAMES { \
+ EXTATTR_NAMESPACE_EMPTY_STRING, \
+ EXTATTR_NAMESPACE_USER_STRING, \
+ EXTATTR_NAMESPACE_SYSTEM_STRING }
+
+/*
+ * This structure defines the required fields of an extended-attribute header.
+ */
+struct extattr {
+ int32_t ea_length; /* length of this attribute */
+ int8_t ea_namespace; /* name space of this attribute */
+ int8_t ea_contentpadlen; /* bytes of padding at end of attribute */
+ int8_t ea_namelength; /* length of attribute name */
+ char ea_name[1]; /* null-terminated attribute name */
+ /* extended attribute content follows */
+};
+
+/*
+ * These macros are used to access and manipulate an extended attribute:
+ *
+ * EXTATTR_NEXT(eap) returns a pointer to the next extended attribute
+ * following eap.
+ * EXTATTR_CONTENT(eap) returns a pointer to the extended attribute
+ * content referenced by eap.
+ * EXTATTR_CONTENT_SIZE(eap) returns the size of the extended attribute
+ * content referenced by eap.
+ * EXTATTR_SET_LENGTHS(eap, contentsize) called after initializing the
+ * attribute name to calculate and set the ea_length, ea_namelength,
+ * and ea_contentpadlen fields of the extended attribute structure.
+ */
+#define EXTATTR_NEXT(eap) \
+ ((struct extattr *)(((void *)(eap)) + (eap)->ea_length))
+#define EXTATTR_CONTENT(eap) (((void *)(eap)) + EXTATTR_BASE_LENGTH(eap))
+#define EXTATTR_CONTENT_SIZE(eap) \
+ ((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen)
+#define EXTATTR_BASE_LENGTH(eap) \
+ ((sizeof(struct extattr) + (eap)->ea_namelength + 7) & ~7)
+#define EXTATTR_SET_LENGTHS(eap, contentsize) do { \
+ KASSERT(((eap)->ea_name[0] != 0), \
+ ("Must initialize name before setting lengths")); \
+ (eap)->ea_namelength = strlen((eap)->ea_name); \
+ (eap)->ea_contentpadlen = ((contentsize) % 8) ? \
+ 8 - ((contentsize) % 8) : 0; \
+ (eap)->ea_length = EXTATTR_BASE_LENGTH(eap) + \
+ (contentsize) + (eap)->ea_contentpadlen; \
+} while (0)
+
#ifdef _KERNEL
#define EXTATTR_MAXNAMELEN NAME_MAX
@@ -56,6 +110,11 @@ int extattr_check_cred(struct vnode *vp, int attrnamespace,
#else
#include <sys/cdefs.h>
+/* User-level definition of KASSERT for macros above */
+#define KASSERT(cond, str) do { \
+ if (cond) { printf("panic: "); printf(str); printf("\n"); exit(1); } \
+} while (0)
+
struct iovec;
__BEGIN_DECLS