Home | History | Annotate | Download | only in squashfs-tools
      1 /*
      2  * Unsquash a squashfs filesystem.  This is a highly compressed read only
      3  * filesystem.
      4  *
      5  * Copyright (c) 2010, 2012
      6  * Phillip Lougher <phillip (at) squashfs.org.uk>
      7  *
      8  * This program is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU General Public License
     10  * as published by the Free Software Foundation; either version 2,
     11  * or (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     21  *
     22  * unsquashfs_xattr.c
     23  */
     24 
     25 #include "unsquashfs.h"
     26 #include "xattr.h"
     27 
     28 #include <sys/xattr.h>
     29 
     30 #ifdef XATTR_NOFOLLOW /* Apple's xattrs */
     31     #define lsetxattr(path_, name_, val_, sz_, flags_) \
     32         setxattr(path_, name_, val_, sz_, 0, flags_ | XATTR_NOFOLLOW)
     33 #endif
     34 
     35 #define NOSPACE_MAX 10
     36 
     37 extern int root_process;
     38 extern int user_xattrs;
     39 
     40 void write_xattr(char *pathname, unsigned int xattr)
     41 {
     42 	unsigned int count;
     43 	struct xattr_list *xattr_list;
     44 	int i;
     45 	static int nonsuper_error = FALSE;
     46 	static int ignore_xattrs = FALSE;
     47 	static int nospace_error = 0;
     48 
     49 	if(ignore_xattrs || xattr == SQUASHFS_INVALID_XATTR ||
     50 			sBlk.s.xattr_id_table_start == SQUASHFS_INVALID_BLK)
     51 		return;
     52 
     53 	xattr_list = get_xattr(xattr, &count, 1);
     54 	if(xattr_list == NULL) {
     55 		ERROR("Failed to read xattrs for file %s\n", pathname);
     56 		return;
     57 	}
     58 
     59 	for(i = 0; i < count; i++) {
     60 		int prefix = xattr_list[i].type & SQUASHFS_XATTR_PREFIX_MASK;
     61 
     62 		if(user_xattrs && prefix != SQUASHFS_XATTR_USER)
     63 			continue;
     64 
     65 		if(root_process || prefix == SQUASHFS_XATTR_USER) {
     66 			int res = lsetxattr(pathname, xattr_list[i].full_name,
     67 				xattr_list[i].value, xattr_list[i].vsize, 0);
     68 
     69 			if(res == -1) {
     70 				if(errno == ENOTSUP) {
     71 					/*
     72 					 * If the destination filesystem cannot
     73 					 * suppport xattrs, print error, and
     74 					 * disable xattr output as this error is
     75 					 * unlikely to go away, and printing
     76 					 * screenfulls of the same error message
     77 					 * is rather annoying
     78 					 */
     79 					ERROR("write_xattr: failed to write "
     80 						"xattr %s for file %s because "
     81 						"extended attributes are not "
     82 						"supported by the destination "
     83 						"filesystem\n",
     84 						xattr_list[i].full_name,
     85 						pathname);
     86 					ERROR("Ignoring xattrs in "
     87 								"filesystem\n");
     88 					ERROR("To avoid this error message, "
     89 						"specify -no-xattrs\n");
     90 					ignore_xattrs = TRUE;
     91 				} else if((errno == ENOSPC || errno == EDQUOT)
     92 						&& nospace_error < NOSPACE_MAX) {
     93 					/*
     94 					 * Many filesystems like ext2/3/4 have
     95 					 * limits on the amount of xattr
     96 					 * data that can be stored per file
     97 					 * (typically one block or 4K), so
     98 					 * we shouldn't disable xattr ouput,
     99 					 * as the error may be restriced to one
    100 					 * file only.  If we get a lot of these
    101 					 * then suppress the error messsage
    102 					 */
    103 					ERROR("write_xattr: failed to write "
    104 						"xattr %s for file %s because "
    105 						"no extended attribute space "
    106 						"remaining (per file or "
    107 						"filesystem limit)\n",
    108 						xattr_list[i].full_name,
    109 						pathname);
    110 					if(++ nospace_error == NOSPACE_MAX)
    111 						ERROR("%d of these errors "
    112 							"printed, further error "
    113 							"messages of this type "
    114 							"are suppressed!\n",
    115 							NOSPACE_MAX);
    116 				} else
    117 					ERROR("write_xattr: failed to write "
    118 						"xattr %s for file %s because "
    119 						"%s\n", xattr_list[i].full_name,
    120 						pathname, strerror(errno));
    121 			}
    122 		} else if(nonsuper_error == FALSE) {
    123 			/*
    124 			 * if extract user xattrs only then
    125 			 * error message is suppressed, if not
    126 			 * print error, and then suppress further error
    127 			 * messages to avoid possible screenfulls of the
    128 			 * same error message!
    129 			 */
    130 			ERROR("write_xattr: could not write xattr %s "
    131 					"for file %s because you're not "
    132 					"superuser!\n",
    133 					xattr_list[i].full_name, pathname);
    134 			ERROR("write_xattr: to avoid this error message, either"
    135 				" specify -user-xattrs, -no-xattrs, or run as "
    136 				"superuser!\n");
    137 			ERROR("Further error messages of this type are "
    138 				"suppressed!\n");
    139 			nonsuper_error = TRUE;
    140 		}
    141 	}
    142 
    143 	free_xattr(xattr_list, count);
    144 }
    145