From 3c4e51fad6dbd595a2fb1e34f11e5a804b9b33ab Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Mon, 19 Nov 2012 00:14:31 +0200 Subject: [PATCH] Various fixes. * src/xattrs.c: Don't mix variable declarations and statements. Use proper data types. Remove improper use of const qualifiers. Use x2nrealloc to reallocate memory buffers. --- src/xattrs.c | 394 +++++++++++++++++++++++++-------------------------- 1 file changed, 190 insertions(+), 204 deletions(-) diff --git a/src/xattrs.c b/src/xattrs.c index abe7b58..5a4bf72 100644 --- a/src/xattrs.c +++ b/src/xattrs.c @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 3, or (at your option) any later + Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but @@ -33,8 +33,8 @@ struct xattrs_mask_map { const char **masks; - int size; - int used; + size_t size; + size_t used; }; /* list of fnmatch patterns */ @@ -136,34 +136,33 @@ perms2acl (int perms) static char * skip_to_ext_fields (char *ptr) { - ptr += strcspn (ptr, ":,\n"); /* skip tag name. Ie. user/group/default/mask */ + /* skip tag name (user/group/default/mask) */ + ptr += strcspn (ptr, ":,\n"); if (*ptr != ':') - return ptr; /* error? no user/group field */ + return ptr; ++ptr; - ptr += strcspn (ptr, ":,\n"); /* skip user/group name */ + ptr += strcspn (ptr, ":,\n"); /* skip user/group name */ if (*ptr != ':') - return ptr; /* error? no perms field */ + return ptr; ++ptr; - ptr += strcspn (ptr, ":,\n"); /* skip perms */ - - if (*ptr != ':') - return ptr; /* no extra fields */ + ptr += strcspn (ptr, ":,\n"); /* skip perms */ return ptr; } /* The POSIX draft allows extra fields after the three main ones. Star uses this to add a fourth field for user/group which is the numeric ID. - We just skip all extra fields atm. */ -static const char * -fixup_extra_acl_fields (const char *ptr) + This function removes such extra fields by overwriting them with the + characters that follow. */ +static char * +fixup_extra_acl_fields (char *ptr) { - char *src = (char *) ptr; - char *dst = (char *) ptr; + char *src = ptr; + char *dst = ptr; while (*src) { @@ -173,14 +172,14 @@ fixup_extra_acl_fields (const char *ptr) src = skip_to_ext_fields (src); len = src - old; if (old != dst) - memmove (dst, old, len); + memmove (dst, old, len); dst += len; - if (*src == ':') /* We have extra fields, skip them all */ - src += strcspn (src, "\n,"); + if (*src == ':') /* We have extra fields, skip them all */ + src += strcspn (src, "\n,"); if ((*src == '\n') || (*src == ',')) - *dst++ = *src++; /* also done when dst == src, but that's ok */ + *dst++ = *src++; /* also done when dst == src, but that's ok */ } if (src != dst) *dst = 0; @@ -188,11 +187,12 @@ fixup_extra_acl_fields (const char *ptr) return ptr; } +/* "system.posix_acl_access" */ static void xattrs__acls_set (struct tar_stat_info const *st, - char const *file_name, int type, - const char *ptr, size_t len, bool def) -{ /* "system.posix_acl_access" */ + char const *file_name, int type, + char *ptr, size_t len, bool def) +{ acl_t acl; if (ptr) @@ -206,10 +206,10 @@ xattrs__acls_set (struct tar_stat_info const *st, else if (acls_option > 0) acl = perms2acl (st->stat.st_mode); else - return; /* don't call acl functions unless we first hit an ACL, or - --acls was passed explicitly */ + return; /* don't call acl functions unless we first hit an ACL, or + --acls was passed explicitly */ - if (acl == (acl_t) NULL) + if (!acl) { call_arg_warn ("acl_from_text", file_name); return; @@ -219,7 +219,7 @@ xattrs__acls_set (struct tar_stat_info const *st, /* warn even if filesystem does not support acls */ WARNOPT (WARN_XATTR_WRITE, (0, errno, - _("acl_set_file_at: Cannot set POSIX ACLs for file '%s'"), + _ ("acl_set_file_at: Cannot set POSIX ACLs for file '%s'"), file_name)); acl_free (acl); @@ -227,25 +227,24 @@ xattrs__acls_set (struct tar_stat_info const *st, static void xattrs__acls_get_a (int parentfd, const char *file_name, - struct tar_stat_info *st, - char **ret_ptr, size_t * ret_len) -{ /* "system.posix_acl_access" */ + struct tar_stat_info *st, + char **ret_ptr, size_t * ret_len) +{ char *val = NULL; ssize_t len; acl_t acl; - if ((acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS)) - == (acl_t) NULL) + if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS))) { if (errno != ENOTSUP) - call_arg_warn ("acl_get_file_at", file_name); + call_arg_warn ("acl_get_file_at", file_name); return; } val = acl_to_text (acl, &len); acl_free (acl); - if (val == NULL) + if (!val) { call_arg_warn ("acl_to_text", file_name); return; @@ -257,27 +256,27 @@ xattrs__acls_get_a (int parentfd, const char *file_name, acl_free (val); } +/* "system.posix_acl_default" */ static void xattrs__acls_get_d (int parentfd, char const *file_name, - struct tar_stat_info *st, - char **ret_ptr, size_t * ret_len) -{ /* "system.posix_acl_default" */ + struct tar_stat_info *st, + char **ret_ptr, size_t * ret_len) +{ char *val = NULL; ssize_t len; acl_t acl; - if ((acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)) - == (acl_t) NULL) + if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT))) { if (errno != ENOTSUP) - call_arg_warn ("acl_get_file_at", file_name); + call_arg_warn ("acl_get_file_at", file_name); return; } val = acl_to_text (acl, &len); acl_free (acl); - if (val == NULL) + if (!val) { call_arg_warn ("acl_to_text", file_name); return; @@ -292,26 +291,26 @@ xattrs__acls_get_d (int parentfd, char const *file_name, static void acls_one_line (const char *prefix, char delim, - const char *aclstring, size_t len) + const char *aclstring, size_t len) { /* support both long and short text representation of posix acls */ struct obstack stk; - obstack_init (&stk); int pref_len = strlen (prefix); const char *oldstring = aclstring; + int pos = 0; if (!aclstring || !len) return; - int pos = 0; + obstack_init (&stk); while (pos <= len) { int move = strcspn (aclstring, ",\n"); if (!move) - break; + break; if (oldstring != aclstring) - obstack_1grow (&stk, delim); + obstack_1grow (&stk, delim); obstack_grow (&stk, prefix, pref_len); obstack_grow (&stk, aclstring, move); @@ -320,60 +319,59 @@ acls_one_line (const char *prefix, char delim, } obstack_1grow (&stk, '\0'); - const char *toprint = obstack_finish (&stk); - fprintf (stdlis, "%s", toprint); + fprintf (stdlis, "%s", (char *) obstack_finish (&stk)); obstack_free (&stk, NULL); } void xattrs_acls_get (int parentfd, char const *file_name, - struct tar_stat_info *st, int fd, int xisfile) + struct tar_stat_info *st, int fd, int xisfile) { if (acls_option > 0) { #ifndef HAVE_POSIX_ACLS static int done = 0; if (!done) - WARN ((0, 0, _("POSIX ACL support is not available"))); + WARN ((0, 0, _("POSIX ACL support is not available"))); done = 1; #else int err = file_has_acl_at (parentfd, file_name, &st->stat); if (err == 0) - return; + return; if (err == -1) - { - call_arg_warn ("file_has_acl_at", file_name); - return; - } + { + call_arg_warn ("file_has_acl_at", file_name); + return; + } xattrs__acls_get_a (parentfd, file_name, st, - &st->acls_a_ptr, &st->acls_a_len); + &st->acls_a_ptr, &st->acls_a_len); if (!xisfile) - xattrs__acls_get_d (parentfd, file_name, st, - &st->acls_d_ptr, &st->acls_d_len); + xattrs__acls_get_d (parentfd, file_name, st, + &st->acls_d_ptr, &st->acls_d_len); #endif } } void xattrs_acls_set (struct tar_stat_info const *st, - char const *file_name, char typeflag) + char const *file_name, char typeflag) { - if ((acls_option > 0) && (typeflag != SYMTYPE)) + if (acls_option > 0 && typeflag != SYMTYPE) { #ifndef HAVE_POSIX_ACLS static int done = 0; if (!done) - WARN ((0, 0, _("POSIX ACL support is not available"))); + WARN ((0, 0, _("POSIX ACL support is not available"))); done = 1; #else xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS, - st->acls_a_ptr, st->acls_a_len, false); - if ((typeflag == DIRTYPE) || (typeflag == GNUTYPE_DUMPDIR)) - xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT, - st->acls_d_ptr, st->acls_d_len, true); + st->acls_a_ptr, st->acls_a_len, false); + if (typeflag == DIRTYPE || typeflag == GNUTYPE_DUMPDIR) + xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT, + st->acls_d_ptr, st->acls_d_len, true); #endif } } @@ -381,26 +379,19 @@ xattrs_acls_set (struct tar_stat_info const *st, static void mask_map_realloc (struct xattrs_mask_map *map) { - if (map->size == 0) - { - map->size = 4; - map->masks = xmalloc (16 * sizeof (char *)); - return; - } - - if (map->size <= map->used) + if (map->used == map->size) { - map->size *= 2; - map->masks = xrealloc (map->masks, map->size * sizeof (char *)); - return; + if (map->size == 0) + map->size = 4; + map->masks = x2nrealloc (map->masks, &map->size, sizeof (map->masks[0])); } } void xattrs_mask_add (const char *mask, bool incl) { - struct xattrs_mask_map *mask_map = incl ? &xattrs_setup.incl - : &xattrs_setup.excl; + struct xattrs_mask_map *mask_map = + incl ? &xattrs_setup.incl : &xattrs_setup.excl; /* ensure there is enough space */ mask_map_realloc (mask_map); /* just assign pointers -- we silently expect that pointer "mask" is valid @@ -426,79 +417,77 @@ xattrs_clear_setup () includes all the user.*, security.*, system.*, etc. available domains */ void xattrs_xattrs_get (int parentfd, char const *file_name, - struct tar_stat_info *st, int fd) + struct tar_stat_info *st, int fd) { if (xattrs_option > 0) { #ifndef HAVE_XATTRS static int done = 0; if (!done) - WARN ((0, 0, _("XATTR support is not available"))); + WARN ((0, 0, _("XATTR support is not available"))); done = 1; #else - static ssize_t xsz = 1024; + static size_t xsz = 1024; static char *xatrs = NULL; ssize_t xret = -1; if (!xatrs) - xatrs = xmalloc (xsz); + xatrs = x2nrealloc (xatrs, &xsz, 1); while (((fd == 0) ? - ((xret = - llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) : - ((xret = flistxattr (fd, xatrs, xsz)) == -1)) - && (errno == ERANGE)) - { - xsz <<= 1; - xatrs = xrealloc (xatrs, xsz); - } + ((xret = + llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) : + ((xret = flistxattr (fd, xatrs, xsz)) == -1)) + && (errno == ERANGE)) + { + xatrs = x2nrealloc (xatrs, &xsz, 1); + } if (xret == -1) - call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name); + call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name); else - { - const char *attr = xatrs; - static ssize_t asz = 1024; - static char *val = NULL; - - if (!val) - val = xmalloc (asz); - - while (xret > 0) - { - size_t len = strlen (attr); - ssize_t aret = 0; - - /* Archive all xattrs during creation, decide at extraction time - * which ones are of interest/use for the target filesystem. */ - while (((fd == 0) - ? ((aret = lgetxattrat (parentfd, file_name, attr, - val, asz)) == -1) - : ((aret = fgetxattr (fd, attr, val, asz)) == -1)) - && (errno == ERANGE)) - { - asz <<= 1; - val = xrealloc (val, asz); - } - - if (aret != -1) - xheader_xattr_add (st, attr, val, aret); - else if (errno != ENOATTR) - call_arg_warn ((fd == 0) ? "lgetxattrat" - : "fgetxattr", file_name); - - attr += len + 1; - xret -= len + 1; - } - } + { + const char *attr = xatrs; + static size_t asz = 1024; + static char *val = NULL; + + if (!val) + val = x2nrealloc (val, &asz, 1); + + while (xret > 0) + { + size_t len = strlen (attr); + ssize_t aret = 0; + + /* Archive all xattrs during creation, decide at extraction time + * which ones are of interest/use for the target filesystem. */ + while (((fd == 0) + ? ((aret = lgetxattrat (parentfd, file_name, attr, + val, asz)) == -1) + : ((aret = fgetxattr (fd, attr, val, asz)) == -1)) + && (errno == ERANGE)) + { + val = x2nrealloc (val, &asz, 1); + } + + if (aret != -1) + xheader_xattr_add (st, attr, val, aret); + else if (errno != ENOATTR) + call_arg_warn ((fd == 0) ? "lgetxattrat" + : "fgetxattr", file_name); + + attr += len + 1; + xret -= len + 1; + } + } #endif } } static void xattrs__fd_set (struct tar_stat_info const *st, - char const *file_name, char typeflag, - const char *attr, const char *ptr, size_t len) + char const *file_name, char typeflag, + const char *attr, const char *ptr, size_t len) { if (ptr) { @@ -506,15 +495,15 @@ xattrs__fd_set (struct tar_stat_info const *st, int ret = -1; if (typeflag != SYMTYPE) - ret = setxattrat (chdir_fd, file_name, attr, ptr, len, 0); + ret = setxattrat (chdir_fd, file_name, attr, ptr, len, 0); else - { - sysname = "lsetxattr"; - ret = lsetxattrat (chdir_fd, file_name, attr, ptr, len, 0); - } + { + sysname = "lsetxattr"; + ret = lsetxattrat (chdir_fd, file_name, attr, ptr, len, 0); + } if (ret == -1) - WARNOPT (WARN_XATTR_WRITE, + WARNOPT (WARN_XATTR_WRITE, (0, errno, _("%s: Cannot set '%s' extended attribute for file '%s'"), sysname, attr, file_name)); @@ -525,56 +514,57 @@ xattrs__fd_set (struct tar_stat_info const *st, zero, otherwise the fgetfileconat is used against correct file descriptor */ void xattrs_selinux_get (int parentfd, char const *file_name, - struct tar_stat_info *st, int fd) + struct tar_stat_info *st, int fd) { if (selinux_context_option > 0) { #if HAVE_SELINUX_SELINUX_H != 1 static int done = 0; if (!done) - WARN ((0, 0, _("SELinux support is not available"))); + WARN ((0, 0, _("SELinux support is not available"))); done = 1; #else - int result = (fd ? fgetfilecon (fd, &st->cntx_name) - : lgetfileconat (parentfd, file_name, &st->cntx_name)); + int result = fd ? + fgetfilecon (fd, &st->cntx_name) + : lgetfileconat (parentfd, file_name, &st->cntx_name); if (result == -1 && errno != ENODATA && errno != ENOTSUP) - call_arg_warn (fd ? "fgetfilecon" : "lgetfileconat", file_name); + call_arg_warn (fd ? "fgetfilecon" : "lgetfileconat", file_name); #endif } } void xattrs_selinux_set (struct tar_stat_info const *st, - char const *file_name, char typeflag) + char const *file_name, char typeflag) { if (selinux_context_option > 0) { #if HAVE_SELINUX_SELINUX_H != 1 static int done = 0; if (!done) - WARN ((0, 0, _("SELinux support is not available"))); + WARN ((0, 0, _("SELinux support is not available"))); done = 1; #else const char *sysname = "setfilecon"; int ret; if (!st->cntx_name) - return; + return; if (typeflag != SYMTYPE) - { - ret = setfileconat (chdir_fd, file_name, st->cntx_name); - sysname = "setfileconat"; - } + { + ret = setfileconat (chdir_fd, file_name, st->cntx_name); + sysname = "setfileconat"; + } else - { - ret = lsetfileconat (chdir_fd, file_name, st->cntx_name); - sysname = "lsetfileconat"; - } + { + ret = lsetfileconat (chdir_fd, file_name, st->cntx_name); + sysname = "lsetfileconat"; + } if (ret == -1) - WARNOPT (WARN_XATTR_WRITE, + WARNOPT (WARN_XATTR_WRITE, (0, errno, _("%s: Cannot set SELinux context for file '%s'"), sysname, file_name)); @@ -597,27 +587,24 @@ xattrs_matches_mask (const char *kw, struct xattrs_mask_map *mm) return false; } +#define USER_DOT_PFX "user." + static bool xattrs_kw_included (const char *kw, bool archiving) { if (xattrs_setup.incl.size) return xattrs_matches_mask (kw, &xattrs_setup.incl); + else if (archiving) + return true; else - { - if (archiving) - return true; - else - return strncmp (kw, "user.", strlen ("user.")) == 0; - } + return strncmp (kw, USER_DOT_PFX, sizeof (USER_DOT_PFX) - 1) == 0; } static bool xattrs_kw_excluded (const char *kw, bool archiving) { - if (!xattrs_setup.excl.size) - return false; - - return xattrs_matches_mask (kw, &xattrs_setup.excl); + return xattrs_setup.excl.size ? + xattrs_matches_mask (kw, &xattrs_setup.excl) : false; } /* Check whether the xattr with keyword KW should be discarded from list of @@ -626,52 +613,50 @@ xattrs_kw_excluded (const char *kw, bool archiving) static bool xattrs_masked_out (const char *kw, bool archiving) { - if (!xattrs_kw_included (kw, archiving)) - return true; - - return xattrs_kw_excluded (kw, archiving); + return xattrs_kw_included (kw, archiving) ? + xattrs_kw_excluded (kw, archiving) : true; } void xattrs_xattrs_set (struct tar_stat_info const *st, - char const *file_name, char typeflag, int later_run) + char const *file_name, char typeflag, int later_run) { if (xattrs_option > 0) { #ifndef HAVE_XATTRS static int done = 0; if (!done) - WARN ((0, 0, _("XATTR support is not available"))); + WARN ((0, 0, _("XATTR support is not available"))); done = 1; #else size_t scan = 0; if (!st->xattr_map_size) - return; + return; for (; scan < st->xattr_map_size; ++scan) - { - char *keyword = st->xattr_map[scan].xkey; - keyword += strlen ("SCHILY.xattr."); - - /* TODO: this 'later_run' workaround is temporary solution -> once - capabilities should become fully supported by it's API and there - should exist something like xattrs_capabilities_set() call. - For a regular files: all extended attributes are restored during - the first run except 'security.capability' which is restored in - 'later_run == 1'. */ - if (typeflag == REGTYPE - && later_run == !!strcmp (keyword, "security.capability")) - continue; - - if (xattrs_masked_out (keyword, false /* extracting */ )) - /* we don't want to restore this keyword */ - continue; - - xattrs__fd_set (st, file_name, typeflag, keyword, - st->xattr_map[scan].xval_ptr, - st->xattr_map[scan].xval_len); - } + { + char *keyword = st->xattr_map[scan].xkey; + keyword += strlen ("SCHILY.xattr."); + + /* TODO: this 'later_run' workaround is temporary solution -> once + capabilities should become fully supported by it's API and there + should exist something like xattrs_capabilities_set() call. + For a regular files: all extended attributes are restored during + the first run except 'security.capability' which is restored in + 'later_run == 1'. */ + if (typeflag == REGTYPE + && later_run == !!strcmp (keyword, "security.capability")) + continue; + + if (xattrs_masked_out (keyword, false /* extracting */ )) + /* we don't want to restore this keyword */ + continue; + + xattrs__fd_set (st, file_name, typeflag, keyword, + st->xattr_map[scan].xval_ptr, + st->xattr_map[scan].xval_len); + } #endif } } @@ -680,7 +665,7 @@ void xattrs_print_char (struct tar_stat_info const *st, char *output) { int i; - + if (verbose_option < 2) { *output = 0; @@ -691,17 +676,18 @@ xattrs_print_char (struct tar_stat_info const *st, char *output) { /* placeholders */ *output = ' '; - *(output + 1) = 0; + output[1] = 0; } if (xattrs_option > 0 && st->xattr_map_size) for (i = 0; i < st->xattr_map_size; ++i) { - char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr."); - if (xattrs_masked_out (keyword, false /* like extracting */ )) - continue; - *output = '*'; - break; + char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr."); + if (!xattrs_masked_out (keyword, false /* like extracting */ )) + { + *output = '*'; + break; + } } if (selinux_context_option > 0 && st->cntx_name) @@ -734,13 +720,13 @@ xattrs_print (struct tar_stat_info const *st) if (xattrs_option && st->xattr_map_size) { int i; + for (i = 0; i < st->xattr_map_size; ++i) - { - char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr."); - if (xattrs_masked_out (keyword, false /* like extracting */ )) - continue; - fprintf (stdlis, " x: %lu %s\n", - (unsigned long) st->xattr_map[i].xval_len, keyword); - } + { + char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr."); + if (!xattrs_masked_out (keyword, false /* like extracting */ )) + fprintf (stdlis, " x: %lu %s\n", + (unsigned long) st->xattr_map[i].xval_len, keyword); + } } } -- 2.45.2