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