summaryrefslogtreecommitdiffstats
path: root/sys/sys/extattr.h
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2007-02-26 06:18:53 +0000
committermckusick <mckusick@FreeBSD.org>2007-02-26 06:18:53 +0000
commit22aa654f0bcb07fd20f8c8543209224495888a8e (patch)
treea9b374203a4a0935735ed723d29c64680d40d3e7 /sys/sys/extattr.h
parent37471781c40bfb3b3acb0a5de707dcbd7f704d75 (diff)
downloadFreeBSD-src-22aa654f0bcb07fd20f8c8543209224495888a8e.zip
FreeBSD-src-22aa654f0bcb07fd20f8c8543209224495888a8e.tar.gz
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 :-)
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 0d9429d..b531e7e 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
OpenPOWER on IntegriCloud