blob: 13f0e352d35ee0301a615f3278a4bbd5aa8ddaeb [file] [log] [blame]
/*
* Unsquash a squashfs filesystem. This is a highly compressed read only
* filesystem.
*
* Copyright (c) 2010, 2012
* Phillip Lougher <phillip@squashfs.org.uk>
*
* 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 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* unsquashfs_xattr.c
*/
#include "unsquashfs.h"
#include "xattr.h"
#include <sys/xattr.h>
#ifdef XATTR_NOFOLLOW /* Apple's xattrs */
#define lsetxattr(path_, name_, val_, sz_, flags_) \
setxattr(path_, name_, val_, sz_, 0, flags_ | XATTR_NOFOLLOW)
#endif
#define NOSPACE_MAX 10
extern int root_process;
extern int user_xattrs;
void write_xattr(char *pathname, unsigned int xattr)
{
unsigned int count;
struct xattr_list *xattr_list;
int i;
static int nonsuper_error = FALSE;
static int ignore_xattrs = FALSE;
static int nospace_error = 0;
if(ignore_xattrs || xattr == SQUASHFS_INVALID_XATTR ||
sBlk.s.xattr_id_table_start == SQUASHFS_INVALID_BLK)
return;
xattr_list = get_xattr(xattr, &count, 1);
if(xattr_list == NULL) {
ERROR("Failed to read xattrs for file %s\n", pathname);
return;
}
for(i = 0; i < count; i++) {
int prefix = xattr_list[i].type & SQUASHFS_XATTR_PREFIX_MASK;
if(user_xattrs && prefix != SQUASHFS_XATTR_USER)
continue;
if(root_process || prefix == SQUASHFS_XATTR_USER) {
int res = lsetxattr(pathname, xattr_list[i].full_name,
xattr_list[i].value, xattr_list[i].vsize, 0);
if(res == -1) {
if(errno == ENOTSUP) {
/*
* If the destination filesystem cannot
* suppport xattrs, print error, and
* disable xattr output as this error is
* unlikely to go away, and printing
* screenfulls of the same error message
* is rather annoying
*/
ERROR("write_xattr: failed to write "
"xattr %s for file %s because "
"extended attributes are not "
"supported by the destination "
"filesystem\n",
xattr_list[i].full_name,
pathname);
ERROR("Ignoring xattrs in "
"filesystem\n");
ERROR("To avoid this error message, "
"specify -no-xattrs\n");
ignore_xattrs = TRUE;
} else if((errno == ENOSPC || errno == EDQUOT)
&& nospace_error < NOSPACE_MAX) {
/*
* Many filesystems like ext2/3/4 have
* limits on the amount of xattr
* data that can be stored per file
* (typically one block or 4K), so
* we shouldn't disable xattr ouput,
* as the error may be restriced to one
* file only. If we get a lot of these
* then suppress the error messsage
*/
ERROR("write_xattr: failed to write "
"xattr %s for file %s because "
"no extended attribute space "
"remaining (per file or "
"filesystem limit)\n",
xattr_list[i].full_name,
pathname);
if(++ nospace_error == NOSPACE_MAX)
ERROR("%d of these errors "
"printed, further error "
"messages of this type "
"are suppressed!\n",
NOSPACE_MAX);
} else
ERROR("write_xattr: failed to write "
"xattr %s for file %s because "
"%s\n", xattr_list[i].full_name,
pathname, strerror(errno));
}
} else if(nonsuper_error == FALSE) {
/*
* if extract user xattrs only then
* error message is suppressed, if not
* print error, and then suppress further error
* messages to avoid possible screenfulls of the
* same error message!
*/
ERROR("write_xattr: could not write xattr %s "
"for file %s because you're not "
"superuser!\n",
xattr_list[i].full_name, pathname);
ERROR("write_xattr: to avoid this error message, either"
" specify -user-xattrs, -no-xattrs, or run as "
"superuser!\n");
ERROR("Further error messages of this type are "
"suppressed!\n");
nonsuper_error = TRUE;
}
}
free_xattr(xattr_list, count);
}