-$Id: CHANGES,v 1.275 2005/05/02 15:13:40 stelian Exp $
+$Id: CHANGES,v 1.282 2006/01/02 15:24:22 stelian Exp $
+
+Changes between versions 0.4b40 and 0.4b41 (released January 2, 2006)
+=====================================================================
+
+1. Fix restore of dumped Access Control Lists. The previous
+ code for EA works fine, but ACLs needed conversion from the
+ ext2/3 disk format to posix_acl format before restoring.
+
+2. Fix some issues with restoration of EA on big endian
+ platforms.
+
+3. Fix restore when the symtab is over 2GB in size.
+
+4. Made the directory hash indexing an optional feature,
+ accessible by the '-H' option of restore, and disable it
+ by default.
+
+5. Fixed dump to not include extended attributes information
+ in the toc (archive) file which confused restore -t.
Changes between versions 0.4b39 and 0.4b40 (released May 2, 2005)
=================================================================
-VERSION= 0.4b40
-DATE= May 2, 2005
+VERSION= 0.4b41
+DATE= January 2, 2006
AR= @AR@
CC= @CC@
* dump and restore backup suit
* Stelian Pop <stelian@popies.net> - AlcĂ´ve <www.alcove.com>, 2000-2002
*
- * $Id: compatlfs.h,v 1.5 2004/03/29 13:57:29 stelian Exp $
+ * $Id: compatlfs.h,v 1.6 2005/07/07 08:47:16 stelian Exp $
*/
/*-
#define _LARGEFILE64_SOURCE
#define OPEN open64
+#define FOPEN fopen64
#define LSEEK lseek64
#define STAT stat64
+#define FSTAT fstat64
#define LSTAT lstat64
#define FTRUNCATE ftruncate64
#define OFF_T __off64_t
#else
#define OPEN open
+#define FOPEN fopen
#define LSEEK lseek
#define STAT stat
+#define FSTAT fstat
#define LSTAT lstat
#define FTRUNCATE ftruncate
#define OFF_T off_t
Begin3
Title: dump and restore for Ext2fs
-Version: 0.4b40
-Entered-date: 01MAY05
+Version: 0.4b41
+Entered-date: 02JAN06
Description: Port of the 4.4BSD dump and restore backup suite
Keywords: backup, filesystem, Ext2fs
Author: University of California, Berkeley
Maintained-by: stelian@popies.net (Stelian Pop)
Primary-site: http://dump.sourceforge.net/
- 0kB dump-0.4b40.tar.gz
+ 0kB dump-0.4b41.tar.gz
0 dump.lsm
Original-site: ftp.freebsd.org /pub/bsd-sources/4.4BSD-Lite2/sbin
dump/*
Summary: Programs for backing up and restoring ext2/ext3 filesystems.
Name: dump
-Version: 0.4b40
+Version: 0.4b41
Release: 1
License: BSD
URL: http://dump.sourceforge.net
Group: Applications/Archiving
Source: dump-%{version}.tar.gz
BuildPrereq: e2fsprogs-devel >= 1.18
-BuildPrereq: libtermcap-devel, readline-devel
+BuildPrereq: libtermcap-devel, readline-devel, ncurses-devel
BuildPrereq: zlib-devel, bzip2-devel
Requires: rmt
BuildRoot: %{_tmppath}/%{name}-root
%{_sbindir}/rrestore.static
%changelog
+* Mon Jan 2 2006 Stelian Pop <stelian@popies.net>
+- dump 0.4b41 released, first packaging.
+
* Fri Jan 21 2005 Stelian Pop <stelian@popies.net>
- dump 0.4b39 released, first packaging.
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: dump.8.in,v 1.57 2004/07/13 08:17:32 stelian Exp $
+.\" $Id: dump.8.in,v 1.58 2005/06/01 13:44:35 stelian Exp $
.\"
.TH DUMP 8 "version __VERSION__ of __DATE__" BSD "System management commands"
.SH NAME
are saved in a regular way. Uses of this flag must be consistent, meaning that
either every dump in an incremental dump set have the flag, or no one has it.
.IP
+If you use this option, be aware that many programs that unpack
+files from archives (e.g. tar, rpm, unzip, dpkg) may set files'
+mtimes to dates in the past. Files installed in this way may not be
+dumped correctly using "dump -m" if the modified mtime is earlier
+than the previous level dump.
+.IP
Tapes written using such 'metadata only' inodes will not be compatible with the
BSD tape format or older versions of
.B restore.
#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.88 2005/03/02 08:46:55 stelian Exp $";
+ "$Id: tape.c,v 1.89 2005/08/20 21:00:48 stelian Exp $";
#endif /* not lint */
#include <config.h>
/* Need to write it to the archive file */
if (! AfileActive && isspcl && (spcl.c_type == TS_END))
AfileActive = 1;
- if (AfileActive && Afile >= 0) {
+ if (AfileActive && Afile >= 0 && !(spcl.c_flags & DR_EXTATTRIBUTES)) {
/* When we dump an inode which is not a directory,
* it means we ended the archive contents */
if (isspcl && (spcl.c_type == TS_INODE) &&
#ifndef lint
static const char rcsid[] =
- "$Id: dirs.c,v 1.32 2005/05/02 15:10:46 stelian Exp $";
+ "$Id: dirs.c,v 1.33 2005/05/28 18:34:47 stelian Exp $";
#endif /* not lint */
#include <config.h>
if (ep == NULL) {
panic("cannot find directory inode %d\n", node.ino);
} else {
- cp = myname(ep);
struct STAT sb;
unsigned long newflags;
+ cp = myname(ep);
if (LSTAT(cp, &sb) < 0) {
warn("unable to stat %s", cp);
do_compare_error;
#ifndef lint
static const char rcsid[] =
- "$Id: main.c,v 1.49 2005/01/14 13:04:56 stelian Exp $";
+ "$Id: main.c,v 1.50 2005/07/07 09:16:08 stelian Exp $";
#endif /* not lint */
#include <config.h>
char *bot_script = NULL;
dump_ino_t volinfo[TP_NINOS];
int wdfd;
+int dirhash_size = 1;
#ifdef USE_QFA
FILE *gTapeposfp;
;
obsolete(&argc, &argv);
while ((ch = getopt(argc, argv,
- "aA:b:CcdD:f:F:hi"
+ "aA:b:CcdD:f:F:hH:i"
#ifdef KERBEROS
"k"
#endif
case 'h':
hflag = 0;
break;
+ case 'H':
+ dirhash_size = strtol(optarg, &p, 10);
+ if (*p)
+ errx(1, "illegal hash size -- %s", optarg);
+ if (dirhash_size < 1)
+ errx(1, "hash size must be greater than 0");
+ break;
#ifdef KERBEROS
case 'k':
dokerberos = 1;
fprintf(stderr,
"usage:"
- "\t%s -C [-cd" kerbflag "lMvVy] [-b blocksize] [-D filesystem] [-f file]\n"
+ "\t%s -C [-cdH" kerbflag "lMvVy] [-b blocksize] [-D filesystem] [-f file]\n"
"\t%s [-F script] [-L limit] [-s fileno]\n"
- "\t%s -i [-acdh" kerbflag "lmMouvVy] [-A file] [-b blocksize] [-f file]\n"
+ "\t%s -i [-acdhH" kerbflag "lmMouvVy] [-A file] [-b blocksize] [-f file]\n"
"\t%s [-F script] " qfaflag "[-s fileno]\n"
#ifdef USE_QFA
- "\t%s -P file [-acdh" kerbflag "lmMuvVy] [-A file] [-b blocksize]\n"
+ "\t%s -P file [-acdhH" kerbflag "lmMuvVy] [-A file] [-b blocksize]\n"
"\t%s [-f file] [-F script] [-s fileno] [-X filelist] [file ...]\n"
#endif
- "\t%s -r [-cd" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n"
+ "\t%s -r [-cdH" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n"
"\t%s [-s fileno] [-T directory]\n"
- "\t%s -R [-cd" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n"
+ "\t%s -R [-cdH" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n"
"\t%s [-s fileno] [-T directory]\n"
- "\t%s -t [-cdh" kerbflag "lMuvVy] [-A file] [-b blocksize] [-f file]\n"
+ "\t%s -t [-cdhH" kerbflag "lMuvVy] [-A file] [-b blocksize] [-f file]\n"
"\t%s [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n"
- "\t%s -x [-acdh" kerbflag "lmMouvVy] [-A file] [-b blocksize] [-f file]\n"
+ "\t%s -x [-acdhH" kerbflag "lmMouvVy] [-A file] [-b blocksize] [-f file]\n"
"\t%s [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n",
__progname, white,
__progname, white,
case 'D':
case 'f':
case 'F':
+ case 'H':
case 'L':
case 'Q':
case 's':
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: restore.8.in,v 1.32 2004/07/13 08:17:32 stelian Exp $
+.\" $Id: restore.8.in,v 1.33 2005/07/07 09:16:08 stelian Exp $
.\"
.TH RESTORE 8 "version __VERSION__ of __DATE__" BSD "System management commands"
.SH NAME
restore \- restore files or file systems from backups made with dump
.SH SYNOPSIS
.B restore \-C
-[\fB\-cdklMvVy\fR]
+[\fB\-cdHklMvVy\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-D \fIfilesystem\fR]
[\fB\-f \fIfile\fR]
[\fB\-T \fIdirectory\fR]
.PP
.B restore \-i
-[\fB\-acdhklmMNouvVy\fR]
+[\fB\-acdhHklmMNouvVy\fR]
[\fB\-A \fIfile\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-f \fIfile\fR]
.PP
.B restore \-P
.I file
-[\fB\-acdhklmMNuvVy\fR]
+[\fB\-acdhHklmMNuvVy\fR]
[\fB\-A \fIfile\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-f \fIfile\fR]
[ \fIfile ... \fR]
.PP
.B restore \-R
-[\fB\-cdklMNuvVy\fR]
+[\fB\-cdHklMNuvVy\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-f \fIfile\fR]
[\fB\-F \fIscript\fR]
[\fB\-T \fIdirectory\fR]
.PP
.B restore \-r
-[\fB\-cdklMNuvVy\fR]
+[\fB\-cdHklMNuvVy\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-f \fIfile\fR]
[\fB\-F \fIscript\fR]
[\fB\-T \fIdirectory\fR]
.PP
.B restore \-t
-[\fB\-cdhklMNuvVy\fR]
+[\fB\-cdhHklMNuvVy\fR]
[\fB\-A \fIfile\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-f \fIfile\fR]
[ \fIfile ... \fR]
.PP
.B restore \-x
-[\fB\-adchklmMNouvVy\fR]
+[\fB\-adchHklmMNouvVy\fR]
[\fB\-A \fIfile\fR]
[\fB\-b \fIblocksize\fR]
[\fB\-f \fIfile\fR]
Extract the actual directory, rather than the files that it references. This
prevents hierarchical restoration of complete subtrees from the dump.
.TP
+.BI \-H " hash_size"
+Use a hashtable having the specified number of entries for storing the
+directories entries instead of a linked list. This hashtable will
+considerably speed up inode lookups (visible especialy in interactive
+mode when adding/removing files from the restore list), but at the
+price of much more memory usage. The default value is 1, meaning no
+hashtable is used.
+.TP
.B \-k
Use Kerberos authentication when contacting the remote tape server. (Only
available if this options was enabled when
#ifndef lint
static const char rcsid[] =
- "$Id: restore.c,v 1.36 2005/03/18 22:12:55 stelian Exp $";
+ "$Id: restore.c,v 1.37 2005/07/07 09:16:08 stelian Exp $";
#endif /* not lint */
#include <config.h>
continue;
if (ep->e_entries == NULL)
continue;
- for (j = 0; j < DIRHASH_SIZE; j++) {
+ for (j = 0; j < dirhash_size; j++) {
for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) {
if (np->e_flags == 0) {
Dprintf(stdout,
for (ep = removelist; ep != NULL; ep = ep->e_next) {
if (ep->e_entries == NULL)
continue;
- for (j = 0; j < DIRHASH_SIZE; j++) {
+ for (j = 0; j < dirhash_size; j++) {
for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) {
if (np->e_type == LEAF) {
if (np->e_flags != 0)
int docont = 0;
if (ep->e_entries != NULL) {
int i;
- for (i = 0; i < DIRHASH_SIZE; i++) {
+ for (i = 0; i < dirhash_size; i++) {
if (ep->e_entries[i] != NULL) {
prev = &ep->e_next;
docont = 1;
* Stelian Pop <stelian@popies.net>, 1999-2000
* Stelian Pop <stelian@popies.net> - AlcĂ´ve <www.alcove.com>, 2000-2002
*
- * $Id: restore.h,v 1.32 2005/05/02 15:10:46 stelian Exp $
+ * $Id: restore.h,v 1.33 2005/07/07 09:16:08 stelian Exp $
*/
/*
extern char filesys[NAMELEN];/* name of dumped filesystem */
extern dump_ino_t volinfo[]; /* which inode on which volume archive info */
extern int wdfd; /* original working directory */
-
-#define DIRHASH_SIZE 1024
+extern int dirhash_size; /* size of the directory hash table */
/*
* Each file in the file system is described by one of these entries
#ifndef lint
static const char rcsid[] =
- "$Id: symtab.c,v 1.25 2005/03/30 13:34:00 stelian Exp $";
+ "$Id: symtab.c,v 1.27 2005/07/07 09:16:08 stelian Exp $";
#endif /* not lint */
/*
*/
#include <config.h>
+#include <compatlfs.h>
#include <sys/param.h>
#include <sys/stat.h>
hash1 = hash0;
hash0 = hash;
}
- return hash0 % DIRHASH_SIZE;
+ return hash0 % dirhash_size;
}
/*
/* search all hash lists for renamed inodes */
if (ep == NULL) {
int j;
- for (j = 0; j < DIRHASH_SIZE; j++) {
+ for (j = 0; j < dirhash_size; j++) {
ep = oldep->e_entries[j];
for ( ; ep != NULL; ep = ep->e_sibling)
if (strcmp(ep->e_name, buf) == 0)
}
np->e_type = type & ~LINK;
if (type & NODE) {
- np->e_entries = calloc(1, DIRHASH_SIZE * sizeof(struct entry *));
+ np->e_entries = calloc(1, dirhash_size * sizeof(struct entry *));
if (np->e_entries == NULL)
panic("unable to allocate directory entries\n");
}
badentry(ep, "freeing referenced directory");
if (ep->e_entries != NULL) {
int i;
- for (i = 0; i < DIRHASH_SIZE; i++) {
+ for (i = 0; i < dirhash_size; i++) {
if (ep->e_entries[i] != NULL)
badentry(ep, "freeing non-empty directory");
}
/* search all hash lists for renamed inodes */
int j;
- for (j = 0; j < DIRHASH_SIZE; j++) {
+ for (j = 0; j < dirhash_size; j++) {
np = ep->e_parent;
entry = np->e_entries[j];
if (entry == ep) {
long mynum = 1, stroff = 0, hashoff = 0;
FILE *fd;
struct symtableheader hdr;
- struct entry *temphash[DIRHASH_SIZE];
+ struct entry **temphash;
Vprintf(stdout, "Check pointing the restore\n");
if (Nflag)
return;
- if ((fd = fopen(filename, "w")) == NULL) {
+ if ((fd = FOPEN(filename, "w")) == NULL) {
warn("fopen");
panic("cannot create save file %s for symbol table\n",
filename);
/*
* Write out e_entries tables
*/
+ temphash = calloc(1, dirhash_size * sizeof(struct entry *));
+ if (temphash == NULL)
+ errx(1, "no memory for saving hashtable");
for (i = WINO; i <= maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
if (ep->e_entries != NULL) {
int j;
- memcpy(temphash, ep->e_entries, DIRHASH_SIZE * sizeof(struct entry *));
- for (j = 0; j < DIRHASH_SIZE; j++) {
+ memcpy(temphash, ep->e_entries, dirhash_size * sizeof(struct entry *));
+ for (j = 0; j < dirhash_size; j++) {
if (temphash[j])
temphash[j] = (struct entry *)ep->e_entries[j]->e_index;
}
- fwrite(temphash, DIRHASH_SIZE, sizeof(struct entry *), fd);
+ fwrite(temphash, dirhash_size, sizeof(struct entry *), fd);
}
}
}
+ free(temphash);
+
/*
* Convert pointers to indexes, and output
*/
(struct entry *)ep->e_sibling->e_index;
if (ep->e_entries != NULL) {
tep->e_entries = (struct entry **)hashoff;
- hashoff += DIRHASH_SIZE * sizeof(struct entry *);
+ hashoff += dirhash_size * sizeof(struct entry *);
}
if (ep->e_next != NULL)
tep->e_next =
struct entry *ep;
struct entry *baseep, *lep;
struct symtableheader hdr;
- struct stat stbuf;
+ struct STAT stbuf;
long i;
int fd;
ep->e_flags |= NEW;
return;
}
- if ((fd = open(filename, O_RDONLY, 0)) < 0) {
+ if ((fd = OPEN(filename, O_RDONLY, 0)) < 0) {
warn("open");
errx(1, "cannot open symbol table file %s", filename);
}
- if (fstat(fd, &stbuf) < 0) {
+ if (FSTAT(fd, &stbuf) < 0) {
warn("stat");
errx(1, "cannot stat symbol table file %s", filename);
}
if (ep->e_type == NODE) {
int i;
ep->e_entries = (struct entry **)(base + hdr.stringsize + (long)ep->e_entries);
- for (i = 0; i < DIRHASH_SIZE; i++) {
+ for (i = 0; i < dirhash_size; i++) {
if (ep->e_entries[i])
ep->e_entries[i] = &baseep[(long)ep->e_entries[i]];
}
#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.89 2005/05/02 15:10:46 stelian Exp $";
+ "$Id: tape.c,v 1.90 2005/06/08 13:24:11 stelian Exp $";
#endif /* not lint */
#include <config.h>
#endif
FLUSHTAPEBUF();
findtapeblksize();
+ cvtflag = 0;
if (gethead(&spcl) == FAIL) {
blkcnt--; /* push back this block */
blksread--;
errx(1, "Tape read error on first record");
memcpy(&spclpt, tapebuf, TP_BSIZE);
+ cvtflag = 0;
if (converthead(&spclpt) == FAIL) {
cvtflag++;
if (converthead(&spclpt) == FAIL) {
if (checksum((int *)buf) == FAIL)
return (FAIL);
if (Bcvt)
- swabst((u_char *)"8i4s31i528bi192b3i", (u_char *)buf);
+ swabst((u_char *)"8i4s1l29i528bi192b4i", (u_char *)buf);
goto good;
}
memcpy(&u_ospcl.s_ospcl, buf, TP_BSIZE);
#ifndef lint
static const char rcsid[] =
- "$Id: utilities.c,v 1.28 2005/03/30 13:21:45 stelian Exp $";
+ "$Id: utilities.c,v 1.29 2005/07/07 09:16:08 stelian Exp $";
#endif /* not lint */
#include <config.h>
badentry(ep, "removenode: not a node");
if (ep->e_entries != NULL) {
int i;
- for (i = 0; i < DIRHASH_SIZE; i++) {
+ for (i = 0; i < dirhash_size; i++) {
if (ep->e_entries[i] != NULL)
badentry(ep, "removenode: non-empty directory");
}
fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
if (ep->e_entries != NULL) {
int i;
- for (i = 0; i < DIRHASH_SIZE; i++) {
+ for (i = 0; i < dirhash_size; i++) {
if (ep->e_entries[i] != NULL) {
fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries[i]));
break;
#ifndef lint
static const char rcsid[] =
- "$Id: xattr.c,v 1.1 2005/05/02 15:10:47 stelian Exp $";
+ "$Id: xattr.c,v 1.3 2005/06/08 13:24:12 stelian Exp $";
#endif /* not lint */
#include <config.h>
return SYSCALL(__NR_llistxattr, path, list, size);
}
+#define POSIX_ACL_XATTR_VERSION 0x0002
+
+#define ACL_UNDEFINED_ID (-1)
+
+#define ACL_USER_OBJ (0x01)
+#define ACL_USER (0x02)
+#define ACL_GROUP_OBJ (0x04)
+#define ACL_GROUP (0x08)
+#define ACL_MASK (0x10)
+#define ACL_OTHER (0x20)
+
+typedef struct {
+ u_int16_t e_tag;
+ u_int16_t e_perm;
+ u_int32_t e_id;
+} posix_acl_xattr_entry;
+
+typedef struct {
+ u_int32_t a_version;
+ posix_acl_xattr_entry a_entries[0];
+} posix_acl_xattr_header;
+
+static inline size_t
+posix_acl_xattr_size(int count)
+{
+ return (sizeof(posix_acl_xattr_header) +
+ (count * sizeof(posix_acl_xattr_entry)));
+}
+
+struct posix_acl_entry {
+ short e_tag;
+ unsigned short e_perm;
+ unsigned int e_id;
+};
+
+struct posix_acl {
+ unsigned int a_count;
+ struct posix_acl_entry a_entries[0];
+};
+
+#define EXT3_ACL_VERSION 0x0001
+
+typedef struct {
+ u_int16_t e_tag;
+ u_int16_t e_perm;
+ u_int32_t e_id;
+} ext3_acl_entry;
+
+typedef struct {
+ u_int16_t e_tag;
+ u_int16_t e_perm;
+} ext3_acl_entry_short;
+
+typedef struct {
+ u_int32_t a_version;
+} ext3_acl_header;
+
+static inline int ext3_acl_count(size_t size)
+{
+ ssize_t s;
+ size -= sizeof(ext3_acl_header);
+ s = size - 4 * sizeof(ext3_acl_entry_short);
+ if (s < 0) {
+ if (size % sizeof(ext3_acl_entry_short))
+ return -1;
+ return size / sizeof(ext3_acl_entry_short);
+ } else {
+ if (s % sizeof(ext3_acl_entry))
+ return -1;
+ return s / sizeof(ext3_acl_entry) + 4;
+ }
+}
+
+int
+posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size) {
+ posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
+ posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
+ int real_size, n;
+
+ real_size = posix_acl_xattr_size(acl->a_count);
+ if (!buffer)
+ return real_size;
+ if (real_size > size) {
+ fprintf(stderr, "ACL: not enough space to convert (%d %d)\n", real_size, size);
+ return -1;
+ }
+
+ ext_acl->a_version = POSIX_ACL_XATTR_VERSION;
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("1i", (u_char *)ext_acl);
+#endif
+
+ for (n=0; n < acl->a_count; n++, ext_entry++) {
+ ext_entry->e_tag = acl->a_entries[n].e_tag;
+ ext_entry->e_perm = acl->a_entries[n].e_perm;
+ ext_entry->e_id = acl->a_entries[n].e_id;
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("2s1i", (u_char *)ext_entry);
+#endif
+ }
+ return real_size;
+}
+
+static struct posix_acl *
+ext3_acl_from_disk(const void *value, size_t size)
+{
+ const char *end = (char *)value + size;
+ int n, count;
+ struct posix_acl *acl;
+
+ if (!value)
+ return NULL;
+ if (size < sizeof(ext3_acl_header)) {
+ fprintf(stderr, "ACL size too little\n");
+ return NULL;
+ }
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("1i", (u_char *)value);
+#endif
+ if (((ext3_acl_header *)value)->a_version != EXT3_ACL_VERSION) {
+ fprintf(stderr, "ACL version unknown\n");
+ return NULL;
+ }
+ value = (char *)value + sizeof(ext3_acl_header);
+ count = ext3_acl_count(size);
+ if (count < 0) {
+ fprintf(stderr, "ACL bad count\n");
+ return NULL;
+ }
+ if (count == 0)
+ return NULL;
+ acl = malloc(sizeof(struct posix_acl) + count * sizeof(struct posix_acl_entry));
+ if (!acl) {
+ fprintf(stderr, "ACL malloc failed\n");
+ return NULL;
+ }
+ acl->a_count = count;
+
+ for (n=0; n < count; n++) {
+ ext3_acl_entry *entry = (ext3_acl_entry *)value;
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("2s", (u_char *)entry);
+#endif
+ if ((char *)value + sizeof(ext3_acl_entry_short) > end)
+ goto fail;
+ acl->a_entries[n].e_tag = entry->e_tag;
+ acl->a_entries[n].e_perm = entry->e_perm;
+ switch(acl->a_entries[n].e_tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ value = (char *)value + sizeof(ext3_acl_entry_short);
+ acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("4b1i", (u_char *)entry);
+#endif
+ value = (char *)value + sizeof(ext3_acl_entry);
+ if ((char *)value > end)
+ goto fail;
+ acl->a_entries[n].e_id = entry->e_id;
+ break;
+
+ default:
+ goto fail;
+ }
+ }
+ if (value != end)
+ goto fail;
+ return acl;
+
+fail:
+ fprintf(stderr, "ACL bad entry\n");
+ free(acl);
+ return NULL;
+}
+
/*
* Dump code starts here :)
*/
end = buffer + XATTR_MAXSIZE;
- if (Bcvt)
- swabst("4i", (u_char *)buffer);
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("4i", (u_char *)buffer);
+#endif
if (HDR(buffer)->h_magic != EXT2_XATTR_MAGIC &&
HDR(buffer)->h_magic != EXT2_XATTR_MAGIC2) {
/* check the on-disk data structure */
entry = FIRST_ENTRY(buffer);
- if (Bcvt)
- swabst("2b1s3i", (u_char *)entry);
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("2b1s3i", (u_char *)entry);
+#endif
while (!IS_LAST_ENTRY(entry)) {
struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(entry);
return FAIL;
}
entry = next;
- if (Bcvt)
- swabst("2b1s3i", (u_char *)entry);
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("2b1s3i", (u_char *)entry);
+#endif
}
return GOOD;
}
entry = EXT2_XATTR_NEXT(entry)) {
char name[XATTR_MAXSIZE], value[XATTR_MAXSIZE];
int off;
+ int convertacl = 0;
switch (entry->e_name_index) {
case EXT2_XATTR_INDEX_USER:
strcpy(name, "user.");
break;
case EXT2_XATTR_INDEX_POSIX_ACL_ACCESS:
+ strcpy(name, "system.posix_acl_access");
+ convertacl = 1;
+ break;
case EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT:
- strcpy(name, "system.");
+ strcpy(name, "system.posix_acl_default");
+ convertacl = 1;
break;
case EXT2_XATTR_INDEX_TRUSTED:
strcpy(name, "trusted.");
memcpy(name + off, entry->e_name, entry->e_name_len);
name[off + entry->e_name_len] = '\0';
-
memcpy(value, buffer + VALUE_OFFSET(buffer, entry), entry->e_value_size);
+ if (convertacl) {
+ struct posix_acl *acl;
+ int size;
+
+ acl = ext3_acl_from_disk(value, entry->e_value_size);
+ if (!acl)
+ return FAIL;
+ size = posix_acl_to_xattr(acl, value, XATTR_MAXSIZE);
+ if (size < 0)
+ return FAIL;
+ entry->e_value_size = size;
+ free(acl);
+ }
+
if (xattr_cb(name, value, entry->e_value_size, private) != GOOD)
return FAIL;
}