Index: head/sbin/restore/dirs.c =================================================================== --- head/sbin/restore/dirs.c +++ head/sbin/restore/dirs.c @@ -645,7 +645,7 @@ if (!Nflag) { if (node.extsize > 0) { if (bufsize >= node.extsize) { - set_extattr_file(cp, buf, node.extsize); + set_extattr(-1, cp, buf, node.extsize, SXA_FILE); } else { fprintf(stderr, "Cannot restore %s%s\n", "extended attributes for ", cp); Index: head/sbin/restore/extern.h =================================================================== --- head/sbin/restore/extern.h +++ head/sbin/restore/extern.h @@ -87,7 +87,12 @@ void rst_closedir(void *); void runcmdshell(void); char *savename(char *); -void set_extattr_file(char *, void *, int); +enum set_extattr_mode { + SXA_FILE, + SXA_LINK, + SXA_FD, +}; +void set_extattr(int, char *, void *, int, enum set_extattr_mode); void setdirmodes(int); void setinput(char *, int); void setup(void); Index: head/sbin/restore/tape.c =================================================================== --- head/sbin/restore/tape.c +++ head/sbin/restore/tape.c @@ -105,8 +105,6 @@ static void findtapeblksize(void); static char *setupextattr(int); static void xtrattr(char *, size_t); -static void set_extattr_link(char *, void *, int); -static void set_extattr_fd(int, char *, void *, int); static void skiphole(void (*)(char *, size_t), size_t *); static int gethead(struct s_spcl *); static void readtape(char *); @@ -627,7 +625,7 @@ } if (linkit(lnkbuf, name, SYMLINK) == GOOD) { if (extsize > 0) - set_extattr_link(name, buf, extsize); + set_extattr(-1, name, buf, extsize, SXA_LINK); (void) lchown(name, uid, gid); (void) lchmod(name, mode); (void) utimensat(AT_FDCWD, name, ctimep, @@ -658,7 +656,7 @@ } else { buf = setupextattr(extsize); getfile(xtrnull, xtrattr, xtrnull); - set_extattr_file(name, buf, extsize); + set_extattr(-1, name, buf, extsize, SXA_FILE); } (void) chown(name, uid, gid); (void) chmod(name, mode); @@ -688,7 +686,7 @@ } else { buf = setupextattr(extsize); getfile(xtrnull, xtrattr, xtrnull); - set_extattr_file(name, buf, extsize); + set_extattr(-1, name, buf, extsize, SXA_FILE); } (void) chown(name, uid, gid); (void) chmod(name, mode); @@ -715,7 +713,7 @@ buf = setupextattr(extsize); getfile(xtrfile, xtrattr, xtrskip); if (extsize > 0) - set_extattr_fd(ofile, name, buf, extsize); + set_extattr(ofile, name, buf, extsize, SXA_FD); (void) fchown(ofile, uid, gid); (void) fchmod(ofile, mode); (void) futimens(ofile, ctimep); @@ -728,12 +726,16 @@ } /* - * Set attributes for a file. + * Set attributes on a file descriptor, link, or file. */ void -set_extattr_file(char *name, void *buf, int size) +set_extattr(int fd, char *name, void *buf, int size, enum set_extattr_mode mode) { struct extattr *eap, *eaend; + const char *method; + ssize_t res; + int error; + char eaname[EXTATTR_MAXNAMELEN + 1]; vprintf(stdout, "Set attributes for %s:", name); eaend = buf + size; @@ -748,77 +750,34 @@ } if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY) continue; - vprintf(stdout, "\n\t%s, (%d bytes), %*s", + snprintf(eaname, sizeof(eaname), "%.*s", + (int)eap->ea_namelength, eap->ea_name); + vprintf(stdout, "\n\t%s, (%d bytes), %s", namespace_names[eap->ea_namespace], eap->ea_length, - eap->ea_namelength, eap->ea_name); + eaname); /* * 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_file(name, eap->ea_namespace, eap->ea_name, - EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) { - dprintf(stdout, " (set using extattr_set_file)"); - 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_file(name, ACL_TYPE_ACCESS, - EXTATTR_CONTENT(eap)) != -1) { - dprintf(stdout, " (set using acl_set_file)"); - 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"); -} - -/* - * Set attributes for a symbolic link. - */ -static void -set_extattr_link(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 (mode == SXA_FD) { + res = extattr_set_fd(fd, eap->ea_namespace, + eaname, EXTATTR_CONTENT(eap), + EXTATTR_CONTENT_SIZE(eap)); + method = "extattr_set_fd"; + } else if (mode == SXA_LINK) { + res = extattr_set_link(name, eap->ea_namespace, + eaname, EXTATTR_CONTENT(eap), + EXTATTR_CONTENT_SIZE(eap)); + method = "extattr_set_link"; + } else if (mode == SXA_FILE) { + res = extattr_set_file(name, eap->ea_namespace, + eaname, EXTATTR_CONTENT(eap), + EXTATTR_CONTENT_SIZE(eap)); + method = "extattr_set_file"; } - 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_link(name, eap->ea_namespace, eap->ea_name, - EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) { - dprintf(stdout, " (set using extattr_set_link)"); + if (res != -1) { + dprintf(stdout, " (set using %s)", method); continue; } /* @@ -827,77 +786,37 @@ * know about. */ if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && - !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) { - if (acl_set_link_np(name, ACL_TYPE_ACCESS, - EXTATTR_CONTENT(eap)) != -1) { - dprintf(stdout, " (set using acl_set_link_np)"); - continue; + strcmp(eaname, POSIX1E_ACL_ACCESS_EXTATTR_NAME) == 0) { + if (mode == SXA_FD) { + error = acl_set_fd(fd, EXTATTR_CONTENT(eap)); + method = "acl_set_fd"; + } else if (mode == SXA_LINK) { + error = acl_set_link_np(name, ACL_TYPE_ACCESS, + EXTATTR_CONTENT(eap)); + method = "acl_set_link_np"; + } else if (mode == SXA_FILE) { + error = acl_set_file(name, ACL_TYPE_ACCESS, + EXTATTR_CONTENT(eap)); + method = "acl_set_file"; } - } - if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && - !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) { - if (acl_set_link_np(name, ACL_TYPE_DEFAULT, - EXTATTR_CONTENT(eap)) != -1) { - dprintf(stdout, " (set using acl_set_link_np)"); + if (error != -1) { + dprintf(stdout, " (set using %s)", method); continue; } } - vprintf(stdout, " (unable to set)"); - } - vprintf(stdout, "\n"); -} - -/* - * 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; + strcmp(eaname, POSIX1E_ACL_DEFAULT_EXTATTR_NAME) == 0) { + if (mode == SXA_LINK) { + error = acl_set_link_np(name, ACL_TYPE_DEFAULT, + EXTATTR_CONTENT(eap)); + method = "acl_set_link_np"; + } else { + error = acl_set_file(name, ACL_TYPE_DEFAULT, + EXTATTR_CONTENT(eap)); + method = "acl_set_file"; } - } - 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)"); + if (error != -1) { + dprintf(stdout, " (set using %s)", method); continue; } } Index: head/sys/sys/extattr.h =================================================================== --- head/sys/sys/extattr.h +++ head/sys/sys/extattr.h @@ -57,10 +57,11 @@ EXTATTR_NAMESPACE_USER_STRING, \ EXTATTR_NAMESPACE_SYSTEM_STRING } +#define EXTATTR_MAXNAMELEN NAME_MAX + #ifdef _KERNEL #include -#define EXTATTR_MAXNAMELEN NAME_MAX struct thread; struct ucred; struct vnode; Index: head/sys/ufs/ufs/extattr.h =================================================================== --- head/sys/ufs/ufs/extattr.h +++ head/sys/ufs/ufs/extattr.h @@ -93,12 +93,14 @@ * content referenced by eap. */ #define EXTATTR_NEXT(eap) \ - ((struct extattr *)(((void *)(eap)) + (eap)->ea_length)) -#define EXTATTR_CONTENT(eap) (((void *)(eap)) + EXTATTR_BASE_LENGTH(eap)) + ((struct extattr *)(((u_char *)(eap)) + (eap)->ea_length)) +#define EXTATTR_CONTENT(eap) \ + (void *)(((u_char *)(eap)) + EXTATTR_BASE_LENGTH(eap)) #define EXTATTR_CONTENT_SIZE(eap) \ ((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen) +/* -1 below compensates for ea_name[1] */ #define EXTATTR_BASE_LENGTH(eap) \ - ((sizeof(struct extattr) + (eap)->ea_namelength + 7) & ~7) + roundup2((sizeof(struct extattr) - 1 + (eap)->ea_namelength), 8) #ifdef _KERNEL