1/* 2 * Copyright (c) 2004 Rob Braun 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Rob Braun nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * 26-Oct-2004 31 * DRI: Rob Braun <bbraun@synack.net> 32 * Ported from xar-unsaxy 16-Apr-2005 33 */ 34/* 35 * Portions Copyright 2006, Apple Computer, Inc. 36 * Christopher Ryan <ryanc@apple.com> 37*/ 38 39#include "config.h" 40#ifndef HAVE_ASPRINTF 41#include "asprintf.h" 42#endif 43#include <stdio.h> 44#include <unistd.h> 45#include "xar.h" 46#include "arcmod.h" 47#include <errno.h> 48#include <string.h> 49#include <fcntl.h> 50#include <sys/types.h> 51#include <sys/ioctl.h> 52#include "ext2.h" 53 54#ifdef HAVE_EXT2FS_EXT2_FS_H 55#include <ext2fs/ext2_fs.h> 56#else 57#if defined(HAVE_LINUX_EXT2_FS_H) 58typedef uint32_t u32; 59typedef uint8_t u8; 60#include <linux/ext2_fs.h> 61#endif 62#endif 63 64#define XAR_EXT2_FORK "ext2" 65 66#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) 67static void x_addprop(xar_file_t f, const char *name) { 68 char opt[1024]; 69 memset(opt, 0, sizeof(opt)); 70 snprintf(opt, sizeof(opt)-1, "%s/%s", XAR_ATTR_FORK, name); 71 xar_prop_set(f, opt, NULL); 72 xar_attr_set(f, opt, "fstype", "ext2"); 73 return; 74} 75#endif 76 77int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) 78{ 79 int ret = 0; 80 81 /* if archiving from a buffer, then there is no place to get extattr */ 82 if ( len ) 83 return 0; 84 85#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) 86 int fd, flags=0, version; 87 char *vstr; 88 const char *opt; 89 90 xar_prop_get(f, "type", &opt); 91 if(!opt) return 0; 92 if( strcmp(opt, "file") != 0 ) { 93 if( strcmp(opt, "hardlink") != 0 ) 94 if( strcmp(opt, "directory") != 0 ) 95 return 0; 96 } 97 98 fd = open(file, O_RDONLY); 99 if( fd < 0 ) { 100 return 0; 101 } 102 if( ioctl(fd, EXT2_IOC_GETVERSION, &version) < 0 ) { 103 ret = 0; 104 goto BAIL; 105 } 106 if( ioctl(fd, EXT2_IOC_GETFLAGS, &flags) < 0 ) { 107 ret = 0; 108 goto BAIL; 109 } 110 111 if( flags == 0 ) goto BAIL; 112 113 xar_prop_set(f, XAR_EXT2_FORK, NULL); 114 asprintf(&vstr, "%d", version); 115 xar_attr_set(f, XAR_EXT2_FORK, "version", vstr); 116 free(vstr); 117 118 if(! (flags & ~EXT2_SECRM_FL) ) 119 x_addprop(f, "SecureDeletion"); 120 if(! (flags & ~EXT2_UNRM_FL) ) 121 x_addprop(f, "Undelete"); 122 if(! (flags & ~EXT2_COMPR_FL) ) 123 x_addprop(f, "Compress"); 124 if(! (flags & ~EXT2_SYNC_FL) ) 125 x_addprop(f, "Synchronous"); 126 if(! (flags & ~EXT2_IMMUTABLE_FL) ) 127 x_addprop(f, "Immutable"); 128 if(! (flags & ~EXT2_APPEND_FL) ) 129 x_addprop(f, "AppendOnly"); 130 if(! (flags & ~EXT2_NODUMP_FL) ) 131 x_addprop(f, "NoDump"); 132 if(! (flags & ~EXT2_NOATIME_FL) ) 133 x_addprop(f, "NoAtime"); 134 if(! (flags & ~EXT2_DIRTY_FL) ) 135 x_addprop(f, "CompDirty"); 136 if(! (flags & ~EXT2_COMPRBLK_FL) ) 137 x_addprop(f, "CompBlock"); 138#ifdef EXT2_NOCOMPR_FL 139 if(! (flags & ~EXT2_NOCOMPR_FL) ) 140 x_addprop(f, "NoCompBlock"); 141#endif 142 if(! (flags & ~EXT2_ECOMPR_FL) ) 143 x_addprop(f, "CompError"); 144 if(! (flags & ~EXT2_BTREE_FL) ) 145 x_addprop(f, "BTree"); 146 if(! (flags & ~EXT2_INDEX_FL) ) 147 x_addprop(f, "HashIndexed"); 148 if(! (flags & ~EXT2_IMAGIC_FL) ) 149 x_addprop(f, "iMagic"); 150#ifdef EXT3_JOURNAL_DATA_FL 151 if(! (flags & ~EXT3_JOURNAL_DATA_FL) ) 152 x_addprop(f, "Journaled"); 153#endif 154 if(! (flags & ~EXT2_NOTAIL_FL) ) 155 x_addprop(f, "NoTail"); 156 if(! (flags & ~EXT2_DIRSYNC_FL) ) 157 x_addprop(f, "DirSync"); 158 if(! (flags & ~EXT2_TOPDIR_FL) ) 159 x_addprop(f, "TopDir"); 160 if(! (flags & ~EXT2_RESERVED_FL) ) 161 x_addprop(f, "Reserved"); 162 163BAIL: 164 close(fd); 165#endif 166 return ret; 167} 168 169#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) 170static int32_t e2prop_get(xar_file_t f, const char *name, char **value) { 171 char v[1024]; 172 173 memset(v, 0, sizeof(v)); 174 snprintf(v, sizeof(v)-1, "%s/%s", XAR_ATTR_FORK, name); 175 return xar_prop_get(f, v, (const char**)value); 176} 177#endif 178 179int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) 180{ 181 /* if extracting to a buffer, then there is no place to write extattr */ 182 if ( len ) 183 return 0; 184 185#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) 186 int fd = -1, version, flags = 0; 187 char *tmp; 188 189 if( xar_prop_get(f, XAR_EXT2_FORK, NULL) == 0 ) { 190 const char *temp; 191 temp = xar_attr_get(f, XAR_EXT2_FORK, "version"); 192 version = strtol(temp, NULL, 10); 193 fd = open(file, O_RDONLY); 194 if( fd < 0 ) 195 return 0; 196 ioctl(fd, EXT2_IOC_SETVERSION, &version); 197 } 198 199 if( xar_prop_get(f, XAR_ATTR_FORK, NULL) ) { 200 if( fd >= 0 ) close(fd); 201 return 0; 202 } 203 204 if( e2prop_get(f, "SecureDeletion", (char **)&tmp) == 0 ) 205 flags |= EXT2_SECRM_FL; 206 if( e2prop_get(f, "Undelete", (char **)&tmp) == 0 ) 207 flags |= EXT2_UNRM_FL ; 208 if( e2prop_get(f, "Compress", (char **)&tmp) == 0 ) 209 flags |= EXT2_COMPR_FL ; 210 if( e2prop_get(f, "Synchronous", (char **)&tmp) == 0 ) 211 flags |= EXT2_SYNC_FL ; 212 if( e2prop_get(f, "SystemImmutable", (char **)&tmp) == 0 ) 213 flags |= EXT2_IMMUTABLE_FL ; 214 if( e2prop_get(f, "AppendOnly", (char **)&tmp) == 0 ) 215 flags |= EXT2_APPEND_FL ; 216 if( e2prop_get(f, "NoDump", (char **)&tmp) == 0 ) 217 flags |= EXT2_NODUMP_FL ; 218 if( e2prop_get(f, "NoAtime", (char **)&tmp) == 0 ) 219 flags |= EXT2_NOATIME_FL ; 220 if( e2prop_get(f, "CompDirty", (char **)&tmp) == 0 ) 221 flags |= EXT2_DIRTY_FL ; 222 if( e2prop_get(f, "CompBlock", (char **)&tmp) == 0 ) 223 flags |= EXT2_COMPRBLK_FL ; 224#ifdef EXT2_NOCOMPR_FL 225 if( e2prop_get(f, "NoCompBlock", (char **)&tmp) == 0 ) 226 flags |= EXT2_NOCOMPR_FL ; 227#endif 228 if( e2prop_get(f, "CompError", (char **)&tmp) == 0 ) 229 flags |= EXT2_ECOMPR_FL ; 230 if( e2prop_get(f, "BTree", (char **)&tmp) == 0 ) 231 flags |= EXT2_BTREE_FL ; 232 if( e2prop_get(f, "HashIndexed", (char **)&tmp) == 0 ) 233 flags |= EXT2_INDEX_FL ; 234 if( e2prop_get(f, "iMagic", (char **)&tmp) == 0 ) 235 flags |= EXT2_IMAGIC_FL ; 236#ifdef EXT3_JOURNAL_DATA_FL 237 if( e2prop_get(f, "Journaled", (char **)&tmp) == 0 ) 238 flags |= EXT3_JOURNAL_DATA_FL ; 239#endif 240 if( e2prop_get(f, "NoTail", (char **)&tmp) == 0 ) 241 flags |= EXT2_NOTAIL_FL ; 242 if( e2prop_get(f, "DirSync", (char **)&tmp) == 0 ) 243 flags |= EXT2_DIRSYNC_FL ; 244 if( e2prop_get(f, "TopDir", (char **)&tmp) == 0 ) 245 flags |= EXT2_TOPDIR_FL ; 246 247 if( fd < 0 ) { 248 fd = open(file, O_RDONLY); 249 if( fd < 0 ) 250 return 0; 251 } 252 253 ioctl(fd, EXT2_IOC_SETFLAGS, &flags); 254 close(fd); 255#endif 256 return 0; 257} 258