Add external attribute dumping and restoring support from FreeBSD.

Does not fully work yet, attributes are being saved and restored correctly,
but don't appear in the restored files somehow.
This commit is contained in:
christos 2021-06-19 13:56:34 +00:00
parent 61337cea22
commit e2325e1f91
14 changed files with 820 additions and 320 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dumprestore.h,v 1.19 2020/04/05 15:25:39 joerg Exp $ */
/* $NetBSD: dumprestore.h,v 1.20 2021/06/19 13:56:34 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -95,7 +95,8 @@ extern union u_spcl {
int64_t __uc_birthtime;
int64_t __uc_atime;
int64_t __uc_mtime;
int32_t __uc_spare4[7];
int32_t __uc_extsize;
int32_t __uc_spare4[6];
uint32_t __uc_file_flags;
int32_t __uc_spare5[2];
uint32_t __uc_uid;
@ -125,6 +126,7 @@ extern union u_spcl {
#define c_mode __c_ino.__uc_ino.__uc_mode
#define c_spare1 __c_ino.__uc_ino.__uc_spare1
#define c_size __c_ino.__uc_ino.__uc_size
#define c_extsize __c_ino.__uc_ino.__uc_extsize
#define c_old_atime __c_ino.__uc_ino.__uc_old_atime
#define c_atime __c_ino.__uc_ino.__uc_atime
#define c_atimensec __c_ino.__uc_ino.__uc_atimensec

View File

@ -1,4 +1,4 @@
/* $NetBSD: dump.h,v 1.59 2020/12/03 08:25:57 kre Exp $ */
/* $NetBSD: dump.h,v 1.60 2021/06/19 13:56:34 christos Exp $ */
/*-
* Copyright (c) 1980, 1993
@ -205,7 +205,7 @@ int mapdirs(ino_t, u_int64_t *);
/* file dumping routines */
void blksout32(int32_t *, int, ino_t);
void blksout64(int64_t *, int, ino_t);
void blksout64(union dinode *, int64_t *, int, ino_t, int);
void dumpino(union dinode *, ino_t);
#ifndef RRESTORE
void dumpmap(char *, int, ino_t);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tape.c,v 1.56 2021/06/07 14:07:32 hannken Exp $ */
/* $NetBSD: tape.c,v 1.57 2021/06/19 13:56:34 christos Exp $ */
/*-
* Copyright (c) 1980, 1991, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)tape.c 8.4 (Berkeley) 5/1/95";
#else
__RCSID("$NetBSD: tape.c,v 1.56 2021/06/07 14:07:32 hannken Exp $");
__RCSID("$NetBSD: tape.c,v 1.57 2021/06/19 13:56:34 christos Exp $");
#endif
#endif /* not lint */
@ -69,8 +69,8 @@ char *nexttape;
static ssize_t atomic_read(int, void *, int);
static ssize_t atomic_write(int, const void *, int);
static void doslave(int, int);
static void enslave(void);
static void doworker(int, int);
static void create_workers(void);
static void flushtape(void);
static void killall(void);
static void proceed(int);
@ -80,11 +80,11 @@ static void tperror(int);
/*
* Concurrent dump mods (Caltech) - disk block reading and tape writing
* are exported to several slave processes. While one slave writes the
* are exported to several worker processes. While one worker writes the
* tape, the others read disk blocks; they pass control of the tape in
* a ring via signals. The parent process traverses the file system and
* sends writeheader()'s and lists of daddr's to the slaves via pipes.
* The following structure defines the instruction packets sent to slaves.
* sends writeheader()'s and lists of daddr's to the workers via pipes.
* The following structure defines the instruction packets sent to workers.
*/
struct req {
daddr_t dblk;
@ -92,20 +92,20 @@ struct req {
};
int reqsiz;
#define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */
struct slave {
#define WORKERS 3 /* 1 worker writing, 1 reading, 1 for slack */
struct worker {
int64_t tapea; /* header number at start of this chunk */
int64_t firstrec; /* record number of this block */
int count; /* count to next header (used for TS_TAPE */
/* after EOT) */
int inode; /* inode that we are currently dealing with */
int fd; /* FD for this slave */
int pid; /* PID for this slave */
int sent; /* 1 == we've sent this slave requests */
int fd; /* FD for this worker */
int pid; /* PID for this worker */
int sent; /* 1 == we've sent this worker requests */
char (*tblock)[TP_BSIZE]; /* buffer for data blocks */
struct req *req; /* buffer for requests */
} slaves[SLAVES+1];
struct slave *slp;
} workers[WORKERS+1];
struct worker *wp;
char (*nextblock)[TP_BSIZE];
@ -138,18 +138,18 @@ alloctape(void)
* packets, so flushtape() can write them together with one write().
* Align tape buffer on page boundary to speed up tape write().
*/
for (i = 0; i <= SLAVES; i++) {
for (i = 0; i <= WORKERS; i++) {
buf = (char *)
xmalloc((unsigned)(reqsiz + writesize + pgoff + TP_BSIZE));
slaves[i].tblock = (char (*)[TP_BSIZE])
workers[i].tblock = (char (*)[TP_BSIZE])
(((long)&buf[ntrec + 1] + pgoff) &~ pgoff);
slaves[i].req = (struct req *)slaves[i].tblock - ntrec - 1;
workers[i].req = (struct req *)workers[i].tblock - ntrec - 1;
}
slp = &slaves[0];
slp->count = 1;
slp->tapea = 0;
slp->firstrec = 0;
nextblock = slp->tblock;
wp = &workers[0];
wp->count = 1;
wp->tapea = 0;
wp->firstrec = 0;
nextblock = wp->tblock;
return(1);
}
@ -157,8 +157,8 @@ void
writerec(const char *dp, int isspcl)
{
slp->req[trecno].dblk = (daddr_t)0;
slp->req[trecno].count = 1;
wp->req[trecno].dblk = (daddr_t)0;
wp->req[trecno].count = 1;
*(union u_spcl *)(*(nextblock)++) = *(const union u_spcl *)dp;
if (isspcl)
lastspclrec = iswap64(spcl.c_tapea);
@ -177,8 +177,8 @@ dumpblock(daddr_t blkno, int size)
dblkno = fsatoda(ufsib, blkno);
tpblks = size >> tp_bshift;
while ((avail = MIN(tpblks, ntrec - trecno)) > 0) {
slp->req[trecno].dblk = dblkno;
slp->req[trecno].count = avail;
wp->req[trecno].dblk = dblkno;
wp->req[trecno].count = avail;
trecno += avail;
spcl.c_tapea = iswap64(iswap64(spcl.c_tapea) + avail);
if (trecno >= ntrec)
@ -279,27 +279,27 @@ flushtape(void)
int i, blks, got;
int64_t lastfirstrec;
int siz = (char *)nextblock - (char *)slp->req;
int siz = (char *)nextblock - (char *)wp->req;
slp->req[trecno].count = 0; /* Sentinel */
wp->req[trecno].count = 0; /* Sentinel */
if (atomic_write(slp->fd, slp->req, siz) != siz)
if (atomic_write(wp->fd, wp->req, siz) != siz)
quite(errno, "error writing command pipe");
slp->sent = 1; /* we sent a request, read the response later */
wp->sent = 1; /* we sent a request, read the response later */
lastfirstrec = slp->firstrec;
lastfirstrec = wp->firstrec;
if (++slp >= &slaves[SLAVES])
slp = &slaves[0];
if (++wp >= &workers[WORKERS])
wp = &workers[0];
/* Read results back from next slave */
if (slp->sent) {
if (atomic_read(slp->fd, &got, sizeof got)
/* Read results back from next worker */
if (wp->sent) {
if (atomic_read(wp->fd, &got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slp->sent = 0;
wp->sent = 0;
/* Check for end of tape */
if (got < writesize) {
@ -309,15 +309,15 @@ flushtape(void)
* Drain the results, don't care what the values were.
* If we read them here then trewind won't...
*/
for (i = 0; i < SLAVES; i++) {
if (slaves[i].sent) {
if (atomic_read(slaves[i].fd,
for (i = 0; i < WORKERS; i++) {
if (workers[i].sent) {
if (atomic_read(workers[i].fd,
&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slaves[i].sent = 0;
workers[i].sent = 0;
}
}
@ -334,11 +334,11 @@ flushtape(void)
if (spcl.c_addr[i] != 0)
blks++;
}
slp->count = lastspclrec + blks + 1 - iswap64(spcl.c_tapea);
slp->tapea = iswap64(spcl.c_tapea);
slp->firstrec = lastfirstrec + ntrec;
slp->inode = curino;
nextblock = slp->tblock;
wp->count = lastspclrec + blks + 1 - iswap64(spcl.c_tapea);
wp->tapea = iswap64(spcl.c_tapea);
wp->firstrec = lastfirstrec + ntrec;
wp->inode = curino;
nextblock = wp->tblock;
trecno = 0;
asize += tenths;
blockswritten += ntrec;
@ -357,7 +357,7 @@ trewind(int eject)
int f;
int got;
for (f = 0; f < SLAVES; f++) {
for (f = 0; f < WORKERS; f++) {
/*
* Drain the results, but unlike EOT we DO (or should) care
* what the return values were, since if we detect EOT after
@ -366,22 +366,22 @@ trewind(int eject)
*
* fixme: punt for now.
*/
if (slaves[f].sent) {
if (atomic_read(slaves[f].fd, &got, sizeof got)
if (workers[f].sent) {
if (atomic_read(workers[f].fd, &got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slaves[f].sent = 0;
workers[f].sent = 0;
if (got != writesize) {
msg("EOT detected in last 2 tape records!\n");
msg("Use a longer tape, decrease the size estimate\n");
quit("or use no size estimate at all");
}
}
(void) close(slaves[f].fd);
(void) close(workers[f].fd);
}
while (wait(NULL) >= 0) /* wait for any signals from slaves */
while (wait(NULL) >= 0) /* wait for any signals from workers */
/* void */;
if (pipeout)
@ -457,29 +457,29 @@ void
rollforward(void)
{
struct req *p, *q, *prev;
struct slave *tslp;
struct worker *twp;
int i, size, got;
int64_t savedtapea;
union u_spcl *ntb, *otb;
tslp = &slaves[SLAVES];
ntb = (union u_spcl *)tslp->tblock[1];
twp = &workers[WORKERS];
ntb = (union u_spcl *)twp->tblock[1];
/*
* Each of the N slaves should have requests that need to
* be replayed on the next tape. Use the extra slave buffers
* (slaves[SLAVES]) to construct request lists to be sent to
* each slave in turn.
* Each of the N workers should have requests that need to
* be replayed on the next tape. Use the extra worker buffers
* (workers[WORKERS]) to construct request lists to be sent to
* each worker in turn.
*/
for (i = 0; i < SLAVES; i++) {
q = &tslp->req[1];
otb = (union u_spcl *)slp->tblock;
for (i = 0; i < WORKERS; i++) {
q = &twp->req[1];
otb = (union u_spcl *)wp->tblock;
/*
* For each request in the current slave, copy it to tslp.
* For each request in the current worker, copy it to twp.
*/
prev = NULL;
for (p = slp->req; p->count > 0; p += p->count) {
for (p = wp->req; p->count > 0; p += p->count) {
*q = *p;
if (p->dblk == 0)
*ntb++ = *otb++; /* copy the datablock also */
@ -494,26 +494,26 @@ rollforward(void)
ntb--;
q -= 1;
q->count = 0;
q = &tslp->req[0];
q = &twp->req[0];
if (i == 0) {
q->dblk = 0;
q->count = 1;
trecno = 0;
nextblock = tslp->tblock;
nextblock = twp->tblock;
savedtapea = iswap64(spcl.c_tapea);
spcl.c_tapea = iswap64(slp->tapea);
spcl.c_tapea = iswap64(wp->tapea);
startnewtape(0);
spcl.c_tapea = iswap64(savedtapea);
lastspclrec = savedtapea - 1;
}
size = (char *)ntb - (char *)q;
if (atomic_write(slp->fd, q, size) != size) {
if (atomic_write(wp->fd, q, size) != size) {
perror(" DUMP: error writing command pipe");
dumpabort(0);
}
slp->sent = 1;
if (++slp >= &slaves[SLAVES])
slp = &slaves[0];
wp->sent = 1;
if (++wp >= &workers[WORKERS])
wp = &workers[0];
q->count = 1;
@ -525,34 +525,34 @@ rollforward(void)
*/
q->dblk = prev->dblk +
prev->count * (TP_BSIZE / DEV_BSIZE);
ntb = (union u_spcl *)tslp->tblock;
ntb = (union u_spcl *)twp->tblock;
} else {
/*
* It wasn't a disk block. Copy the data to its
* new location in the buffer.
*/
q->dblk = 0;
*((union u_spcl *)tslp->tblock) = *ntb;
ntb = (union u_spcl *)tslp->tblock[1];
*((union u_spcl *)twp->tblock) = *ntb;
ntb = (union u_spcl *)twp->tblock[1];
}
}
slp->req[0] = *q;
nextblock = slp->tblock;
wp->req[0] = *q;
nextblock = wp->tblock;
if (q->dblk == 0)
nextblock++;
trecno = 1;
/*
* Clear the first slaves' response. One hopes that it
* Clear the first workers' response. One hopes that it
* worked ok, otherwise the tape is much too short!
*/
if (slp->sent) {
if (atomic_read(slp->fd, &got, sizeof got)
if (wp->sent) {
if (atomic_read(wp->fd, &got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slp->sent = 0;
wp->sent = 0;
if (got != writesize) {
quit("EOT detected at start of the tape");
@ -680,31 +680,31 @@ restore_check_point:
dumpabort(0);
}
enslave(); /* Share open tape file descriptor with slaves */
create_workers(); /* Share open tape file descriptor with workers */
asize = 0;
blocksthisvol = 0;
if (top)
newtape++; /* new tape signal */
spcl.c_count = iswap32(slp->count);
spcl.c_count = iswap32(wp->count);
/*
* measure firstrec in TP_BSIZE units since restore doesn't
* know the correct ntrec value...
*/
spcl.c_firstrec = iswap32(slp->firstrec);
spcl.c_firstrec = iswap32(wp->firstrec);
spcl.c_volume = iswap32(iswap32(spcl.c_volume) + 1);
spcl.c_type = iswap32(TS_TAPE);
if (!is_ufs2)
spcl.c_flags = iswap32(iswap32(spcl.c_flags)
| DR_NEWHEADER);
writeheader((ino_t)slp->inode);
writeheader((ino_t)wp->inode);
if (!is_ufs2)
spcl.c_flags = iswap32(iswap32(spcl.c_flags) &
~ DR_NEWHEADER);
msg("Volume %d started at: %s", tapeno, ctime(&tstart_volume));
if (tapeno > 1)
msg("Volume %d begins with blocks from inode %d\n",
tapeno, slp->inode);
tapeno, wp->inode);
}
}
@ -739,7 +739,7 @@ Exit(int status)
}
/*
* proceed - handler for SIGUSR2, used to synchronize IO between the slaves.
* proceed - handler for SIGUSR2, used to synchronize IO between the workers.
*/
static void
proceed(int signo __unused)
@ -748,7 +748,7 @@ proceed(int signo __unused)
}
void
enslave(void)
create_workers(void)
{
int cmd[2];
int i, j;
@ -758,36 +758,36 @@ enslave(void)
signal(SIGTERM, dumpabort); /* Slave sends SIGTERM on dumpabort() */
signal(SIGPIPE, sigpipe);
signal(SIGUSR1, tperror); /* Slave sends SIGUSR1 on tape errors */
signal(SIGUSR2, proceed); /* Slave sends SIGUSR2 to next slave */
signal(SIGUSR2, proceed); /* Slave sends SIGUSR2 to next worker */
for (i = 0; i < SLAVES; i++) {
if (i == slp - &slaves[0]) {
for (i = 0; i < WORKERS; i++) {
if (i == wp - &workers[0]) {
caught = 1;
} else {
caught = 0;
}
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, cmd) < 0 ||
(slaves[i].pid = fork()) < 0)
quite(errno, "too many slaves, %d (recompile smaller)",
(workers[i].pid = fork()) < 0)
quite(errno, "too many workers, %d (recompile smaller)",
i);
slaves[i].fd = cmd[1];
slaves[i].sent = 0;
if (slaves[i].pid == 0) { /* Slave starts up here */
workers[i].fd = cmd[1];
workers[i].sent = 0;
if (workers[i].pid == 0) { /* Slave starts up here */
for (j = 0; j <= i; j++)
(void) close(slaves[j].fd);
(void) close(workers[j].fd);
signal(SIGINT, SIG_IGN); /* Master handles this */
signal(SIGINFO, SIG_IGN);
doslave(cmd[0], i);
doworker(cmd[0], i);
Exit(X_FINOK);
}
}
for (i = 0; i < SLAVES; i++)
(void) atomic_write(slaves[i].fd,
&slaves[(i + 1) % SLAVES].pid,
sizeof slaves[0].pid);
for (i = 0; i < WORKERS; i++)
(void) atomic_write(workers[i].fd,
&workers[(i + 1) % WORKERS].pid,
sizeof workers[0].pid);
master = 0;
}
@ -797,10 +797,10 @@ killall(void)
{
int i;
for (i = 0; i < SLAVES; i++)
if (slaves[i].pid > 0) {
(void) kill(slaves[i].pid, SIGKILL);
slaves[i].sent = 0;
for (i = 0; i < WORKERS; i++)
if (workers[i].pid > 0) {
(void) kill(workers[i].pid, SIGKILL);
workers[i].sent = 0;
}
}
@ -812,9 +812,9 @@ killall(void)
* get the lock back for the next cycle by swapping descriptors.
*/
static void
doslave(int cmd, int slave_number __unused)
doworker(int cmd, int worker_number __unused)
{
int nread, nextslave, size, wrote, eot_count, werror;
int nread, nextworker, size, wrote, eot_count, werror;
sigset_t nsigset, osigset;
wrote = 0;
@ -823,33 +823,33 @@ doslave(int cmd, int slave_number __unused)
*/
(void) close(diskfd);
if ((diskfd = open(disk_dev, O_RDONLY)) < 0)
quite(errno, "slave couldn't reopen disk");
quite(errno, "worker couldn't reopen disk");
/*
* Need the pid of the next slave in the loop...
* Need the pid of the next worker in the loop...
*/
if ((nread = atomic_read(cmd, &nextslave, sizeof nextslave))
!= sizeof nextslave) {
quit("master/slave protocol botched - didn't get pid"
" of next slave");
if ((nread = atomic_read(cmd, &nextworker, sizeof nextworker))
!= sizeof nextworker) {
quit("master/worker protocol botched - didn't get pid"
" of next worker");
}
/*
* Get list of blocks to dump, read the blocks into tape buffer
*/
while ((nread = atomic_read(cmd, slp->req, reqsiz)) == reqsiz) {
struct req *p = slp->req;
while ((nread = atomic_read(cmd, wp->req, reqsiz)) == reqsiz) {
struct req *p = wp->req;
for (trecno = 0; trecno < ntrec;
trecno += p->count, p += p->count) {
if (p->dblk) {
bread(p->dblk, slp->tblock[trecno],
bread(p->dblk, wp->tblock[trecno],
p->count * TP_BSIZE);
} else {
if (p->count != 1 || atomic_read(cmd,
slp->tblock[trecno],
wp->tblock[trecno],
TP_BSIZE) != TP_BSIZE)
quit("master/slave protocol botched");
quit("master/worker protocol botched");
}
}
@ -869,16 +869,16 @@ doslave(int cmd, int slave_number __unused)
while (eot_count < 10 && size < writesize) {
#ifdef RDUMP
if (host)
wrote = rmtwrite(slp->tblock[0]+size,
wrote = rmtwrite(wp->tblock[0]+size,
writesize-size);
else
#endif
wrote = write(tapefd, slp->tblock[0]+size,
wrote = write(tapefd, wp->tblock[0]+size,
writesize-size);
werror = errno;
#ifdef WRITEDEBUG
fprintf(stderr, "slave %d wrote %d werror %d\n",
slave_number, wrote, werror);
fprintf(stderr, "worker %d wrote %d werror %d\n",
worker_number, wrote, werror);
#endif
if (wrote < 0)
break;
@ -890,8 +890,8 @@ doslave(int cmd, int slave_number __unused)
#ifdef WRITEDEBUG
if (size != writesize)
fprintf(stderr,
"slave %d only wrote %d out of %d bytes and gave up.\n",
slave_number, size, writesize);
"worker %d only wrote %d out of %d bytes and gave up.\n",
worker_number, size, writesize);
#endif
/*
@ -919,10 +919,10 @@ doslave(int cmd, int slave_number __unused)
}
/*
* If partial write, don't want next slave to go.
* If partial write, don't want next worker to go.
* Also jolts him awake.
*/
(void) kill(nextslave, SIGUSR2);
(void) kill(nextworker, SIGUSR2);
}
printcachestats();
if (nread != 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: traverse.c,v 1.52 2019/03/01 16:42:11 christos Exp $ */
/* $NetBSD: traverse.c,v 1.53 2021/06/19 13:56:34 christos Exp $ */
/*-
* Copyright (c) 1980, 1988, 1991, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)traverse.c 8.7 (Berkeley) 6/15/95";
#else
__RCSID("$NetBSD: traverse.c,v 1.52 2019/03/01 16:42:11 christos Exp $");
__RCSID("$NetBSD: traverse.c,v 1.53 2021/06/19 13:56:34 christos Exp $");
#endif
#endif /* not lint */
@ -45,6 +45,7 @@ __RCSID("$NetBSD: traverse.c,v 1.52 2019/03/01 16:42:11 christos Exp $");
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fts.h>
@ -58,8 +59,10 @@ __RCSID("$NetBSD: traverse.c,v 1.52 2019/03/01 16:42:11 christos Exp $");
#define HASDUMPEDFILE 0x1
#define HASSUBDIRS 0x2
static int appendextdata(union dinode *dp);
static void writeextdata(union dinode *dp, ino_t ino, int added);
static int dirindir(ino_t, daddr_t, int, off_t *, u_int64_t *, int);
static void dmpindir(ino_t, daddr_t, int, off_t *);
static void dmpindir(union dinode *dp, ino_t, daddr_t, int, off_t *);
static int searchdir(ino_t, daddr_t, long, off_t, u_int64_t *, int);
/*
@ -475,7 +478,7 @@ searchdir(ino_t dino, daddr_t blkno, long size, off_t filesize,
void
dumpino(union dinode *dp, ino_t ino)
{
int ind_level, cnt;
int ind_level, cnt, last, added;
off_t size;
char buf[TP_BSIZE];
daddr_t blk;
@ -504,6 +507,7 @@ dumpino(union dinode *dp, ino_t ino)
ffs_dinode2_swap(&dp->dp2, &dp->dp2);
spcl.c_mode = dp->dp2.di_mode;
spcl.c_size = dp->dp2.di_size;
spcl.c_extsize = dp->dp2.di_extsize;
spcl.c_atime = dp->dp2.di_atime;
spcl.c_atimensec = dp->dp2.di_atimensec;
spcl.c_mtime = dp->dp2.di_mtime;
@ -539,6 +543,7 @@ dumpino(union dinode *dp, ino_t ino)
) {
spcl.c_addr[0] = 1;
spcl.c_count = iswap32(1);
added = appendextdata(dp);
writeheader(ino);
if (is_ufs2)
shortlink = dp->dp2.di_db;
@ -547,6 +552,7 @@ dumpino(union dinode *dp, ino_t ino)
memmove(buf, shortlink, DIP(dp, size));
buf[DIP(dp, size)] = '\0';
writerec(buf, 0);
writeextdata(dp, ino, added);
return;
}
/* fall through */
@ -561,19 +567,24 @@ dumpino(union dinode *dp, ino_t ino)
case IFSOCK:
case IFCHR:
case IFBLK:
added = appendextdata(dp);
writeheader(ino);
writeextdata(dp, ino, added);
return;
default:
msg("Warning: undefined file type 0%o\n", DIP(dp, mode) & IFMT);
return;
}
if (DIP(dp, size) > UFS_NDADDR * ufsib->ufs_bsize)
if (DIP(dp, size) > UFS_NDADDR * ufsib->ufs_bsize) {
cnt = UFS_NDADDR * ufsib->ufs_frag;
else
last = 0;
} else {
cnt = howmany(DIP(dp, size), ufsib->ufs_fsize);
last = 1;
}
if (is_ufs2)
blksout64(&dp->dp2.di_db[0], cnt, ino);
blksout64(dp, &dp->dp2.di_db[0], cnt, ino, last);
else
blksout32(&dp->dp1.di_db[0], cnt, ino);
@ -584,7 +595,7 @@ dumpino(union dinode *dp, ino_t ino)
blk = iswap64(dp->dp2.di_ib[ind_level]);
else
blk = iswap32(dp->dp1.di_ib[ind_level]);
dmpindir(ino, blk, ind_level, &size);
dmpindir(dp, ino, blk, ind_level, &size);
if (size <= 0)
return;
}
@ -594,9 +605,9 @@ dumpino(union dinode *dp, ino_t ino)
* Read indirect blocks, and pass the data blocks to be dumped.
*/
static void
dmpindir(ino_t ino, daddr_t blk, int ind_level, off_t *size)
dmpindir(union dinode *dp, ino_t ino, daddr_t blk, int ind_level, off_t *size)
{
int i, cnt;
int i, cnt, last;
union {
int32_t i32[MAXBSIZE / sizeof (int32_t)];
int64_t i64[MAXBSIZE / sizeof (int64_t)];
@ -610,13 +621,16 @@ dmpindir(ino_t ino, daddr_t blk, int ind_level, off_t *size)
else
memset(&idblk, 0, (int)ufsib->ufs_bsize);
if (ind_level <= 0) {
if (*size < ufsib->ufs_nindir * ufsib->ufs_bsize)
if (*size < ufsib->ufs_nindir * ufsib->ufs_bsize) {
cnt = howmany(*size, ufsib->ufs_fsize);
else
last = 0;
} else {
cnt = ufsib->ufs_nindir * ufsib->ufs_frag;
last = 1;
}
*size -= ufsib->ufs_nindir * ufsib->ufs_bsize;
if (is_ufs2)
blksout64(&idblk.i64[0], cnt, ino);
blksout64(dp, &idblk.i64[0], cnt, ino, last);
else
blksout32(&idblk.i32[0], cnt, ino);
return;
@ -627,7 +641,7 @@ dmpindir(ino_t ino, daddr_t blk, int ind_level, off_t *size)
iblk = iswap64(idblk.i64[i]);
else
iblk = iswap32(idblk.i32[i]);
dmpindir(ino, iblk, ind_level, size);
dmpindir(dp, ino, iblk, ind_level, size);
if (*size <= 0)
return;
}
@ -669,24 +683,40 @@ blksout32(int32_t *blkp, int frags, ino_t ino)
}
void
blksout64(int64_t *blkp, int frags, ino_t ino)
blksout64(union dinode *dp, int64_t *blkp, int frags, ino_t ino, int last)
{
int64_t *bp;
int i, j, count, blks, tbperdb;
int i, j, count, blks, tbperdb, added = 0;
static int writingextdata = 0;
blks = howmany(frags * ufsib->ufs_fsize, TP_BSIZE);
if (last) {
int resid;
int extsize = iswap32(spcl.c_extsize);
if (writingextdata)
resid = howmany(ufsib->ufs_qfmask & extsize,
TP_BSIZE);
else
resid = howmany(ufsib->ufs_qfmask & dp->dp2.di_size,
TP_BSIZE);
if (resid > 0)
blks -= howmany(ufsib->ufs_fsize, TP_BSIZE) - resid;
}
tbperdb = ufsib->ufs_bsize >> tp_bshift;
for (i = 0; i < blks; i += TP_NINDIR) {
if (i + TP_NINDIR > blks)
count = blks;
else
count = i + TP_NINDIR;
assert(count <= TP_NINDIR + i);
for (j = i; j < count; j++)
if (blkp[j / tbperdb] != 0)
spcl.c_addr[j - i] = 1;
else
spcl.c_addr[j - i] = 0;
spcl.c_count = iswap32(count - i);
if (last && count == blks && !writingextdata)
added = appendextdata(dp);
writeheader(ino);
bp = &blkp[i / tbperdb];
for (j = i; j < count; j += tbperdb, bp++)
@ -697,8 +727,128 @@ blksout64(int64_t *blkp, int frags, ino_t ino)
dumpblock(iswap64(*bp), (count - j) * TP_BSIZE);
}
spcl.c_type = iswap32(TS_ADDR);
spcl.c_count = 0;
if (last && count == blks && !writingextdata) {
writingextdata = 1;
writeextdata(dp, ino, added);
writingextdata = 0;
}
}
}
/*
* If there is room in the current block for the extended attributes
* as well as the file data, update the header to reflect the added
* attribute data at the end. Attributes are placed at the end so that
* old versions of restore will correctly restore the file and simply
* discard the extra data at the end that it does not understand.
* The attribute data is dumped following the file data by the
* writeextdata() function (below).
*/
static int
appendextdata(union dinode *dp)
{
int i, blks, tbperdb, count, extsize;
count = iswap32(spcl.c_count);
extsize = iswap32(spcl.c_extsize);
/*
* If no extended attributes, there is nothing to do.
*/
if (extsize == 0)
return (0);
/*
* If there is not enough room at the end of this block
* to add the extended attributes, then rather than putting
* part of them here, we simply push them entirely into a
* new block rather than putting some here and some later.
*/
if (extsize > UFS_NXADDR * ufsib->ufs_bsize)
blks = howmany(UFS_NXADDR * ufsib->ufs_bsize, TP_BSIZE);
else
blks = howmany(extsize, TP_BSIZE);
if (count + blks > TP_NINDIR)
return (0);
/*
* Update the block map in the header to indicate the added
* extended attribute. They will be appended after the file
* data by the writeextdata() routine.
*/
tbperdb = ufsib->ufs_bsize >> tp_bshift;
assert(count + blks < TP_NINDIR);
for (i = 0; i < blks; i++)
if (&dp->dp2.di_extb[i / tbperdb] != 0)
spcl.c_addr[count + i] = 1;
else
spcl.c_addr[count + i] = 0;
spcl.c_count = iswap32(count + blks);
return (blks);
}
/*
* Dump the extended attribute data. If there was room in the file
* header, then all we need to do is output the data blocks. If there
* was not room in the file header, then an additional TS_ADDR header
* is created to hold the attribute data.
*/
static void
writeextdata(union dinode *dp, ino_t ino, int added)
{
int i, frags, blks, tbperdb, last, extsize;
int64_t *bp;
off_t size;
extsize = iswap32(spcl.c_extsize);
/*
* If no extended attributes, there is nothing to do.
*/
if (extsize == 0)
return;
/*
* If there was no room in the file block for the attributes,
* dump them out in a new block, otherwise just dump the data.
*/
if (added == 0) {
if (extsize > UFS_NXADDR * ufsib->ufs_bsize) {
frags = UFS_NXADDR * ufsib->ufs_frag;
last = 0;
} else {
frags = howmany(extsize, ufsib->ufs_fsize);
last = 1;
}
blksout64(dp, &dp->dp2.di_extb[0], frags, ino, last);
} else {
if (extsize > UFS_NXADDR * ufsib->ufs_bsize)
blks = howmany(UFS_NXADDR * ufsib->ufs_bsize, TP_BSIZE);
else
blks = howmany(extsize, TP_BSIZE);
tbperdb = ufsib->ufs_bsize >> tp_bshift;
for (i = 0; i < blks; i += tbperdb) {
bp = &dp->dp2.di_extb[i / tbperdb];
if (*bp != 0) {
if (i + tbperdb <= blks)
dumpblock(iswap64(*bp), (int)ufsib->ufs_bsize);
else
dumpblock(iswap64(*bp), (blks - i) * TP_BSIZE);
}
}
}
/*
* If an indirect block is added for extended attributes, then
* di_exti below should be changed to the structure element
* that references the extended attribute indirect block. This
* definition is here only to make it compile without complaint.
*/
#define di_exti di_spare[0]
/*
* If the extended attributes fall into an indirect block,
* dump it as well.
*/
if ((size = extsize - UFS_NXADDR * ufsib->ufs_bsize) > 0)
dmpindir(dp, ino, dp->dp2.di_exti, 0, &size);
}
/*
* Dump a map to the tape.

View File

@ -1,4 +1,4 @@
/* $NetBSD: dirs.c,v 1.51 2015/03/02 03:17:24 enami Exp $ */
/* $NetBSD: dirs.c,v 1.52 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)dirs.c 8.7 (Berkeley) 5/1/95";
#else
__RCSID("$NetBSD: dirs.c,v 1.51 2015/03/02 03:17:24 enami Exp $");
__RCSID("$NetBSD: dirs.c,v 1.52 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -89,7 +89,8 @@ struct modeinfo {
mode_t mode;
uid_t uid;
gid_t gid;
int flags;
u_int flags;
int extsize;
};
/*
@ -108,7 +109,7 @@ struct rstdirdesc {
* Global variables for this file.
*/
static long seekpt;
static FILE *df;
static FILE *df, *mf;
static RST_DIR *dirp;
static char dirfile[MAXPATHLEN] = "#"; /* No file */
static char modefile[MAXPATHLEN] = "#"; /* No file */
@ -123,16 +124,18 @@ struct odirect {
char d_name[ODIRSIZ];
};
static struct inotab *allocinotab(FILE *, struct context *, long);
static struct inotab *allocinotab(struct context *, long);
static void dcvt(struct odirect *, struct direct *);
static void flushent(void);
static struct inotab *inotablookup(ino_t);
static RST_DIR *opendirfile(const char *);
static void putdir(char *, long);
static void putdir(char *, size_t);
static void putdirattrs(char *, size_t);
static void putent(struct direct *);
static void rst_seekdir(RST_DIR *, long, long);
static long rst_telldir(RST_DIR *);
static struct direct *searchdir(ino_t, char *);
static void fail_dirtmp(char *);
/*
* Extract directory contents, building up a directory structure
@ -143,18 +146,16 @@ static struct direct *searchdir(ino_t, char *);
void
extractdirs(int genmode)
{
FILE *mf;
int i, dfd, mfd;
struct inotab *itp;
struct direct nulldir;
mf = NULL;
vprintf(stdout, "Extract directories from tape\n");
(void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%d",
tmpdir, (int)dumpdate);
(void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%jd",
tmpdir, (intmax_t)dumpdate);
if (command != 'r' && command != 'R') {
(void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%d-XXXXXX",
tmpdir, (int)dumpdate);
(void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%jd-XXXXXX",
tmpdir, (intmax_t)dumpdate);
if ((dfd = mkstemp(dirfile)) == -1)
err(1, "cannot mkstemp temporary file %s", dirfile);
df = fdopen(dfd, "w");
@ -165,11 +166,11 @@ extractdirs(int genmode)
err(1, "cannot open temporary file %s", dirfile);
if (genmode != 0) {
(void) snprintf(modefile, sizeof(modefile), "%s/rstmode%d",
tmpdir, (int)dumpdate);
(void) snprintf(modefile, sizeof(modefile), "%s/rstmode%jd",
tmpdir, (intmax_t)dumpdate);
if (command != 'r' && command != 'R') {
(void) snprintf(modefile, sizeof(modefile),
"%s/rstmode%d-XXXXXX", tmpdir, (int)dumpdate);
"%s/rstmode%jd-XXXXXX", tmpdir, (intmax_t)dumpdate);
if ((mfd = mkstemp(modefile)) == -1)
err(1, "cannot mkstemp temporary file %s",
modefile);
@ -188,25 +189,24 @@ extractdirs(int genmode)
for (;;) {
curfile.name = "<directory file - name unknown>";
curfile.action = USING;
if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR) {
(void) fclose(df);
dirp = opendirfile(dirfile);
if (dirp == NULL)
fprintf(stderr, "opendirfile: %s\n",
strerror(errno));
if (mf != NULL)
(void) fclose(mf);
i = dirlookup(dot);
if (i == 0)
panic("Root directory is not on tape\n");
return;
}
itp = allocinotab(mf, &curfile, seekpt);
getfile(putdir, xtrnull);
if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR)
break;
itp = allocinotab(&curfile, seekpt);
getfile(putdir, putdirattrs, xtrnull);
putent(&nulldir);
flushent();
itp->t_size = seekpt - itp->t_seekpt;
}
if (fclose(df) != 0)
fail_dirtmp(dirfile);
dirp = opendirfile(dirfile);
if (dirp == NULL)
fprintf(stderr, "opendirfile: %s\n", strerror(errno));
if (mf != NULL && fclose(mf) != 0)
fail_dirtmp(modefile);
i = dirlookup(dot);
if (i == 0)
panic("Root directory is not on tape\n");
}
/*
@ -272,11 +272,10 @@ treescan(const char *pname, ino_t ino, long (*todo)(const char *, ino_t, int))
while (dp != NULL) {
locname[namelen] = '\0';
if (namelen + dp->d_namlen >= sizeof(locname)) {
fprintf(stderr, "%s%s: name exceeds %lu char\n",
locname, dp->d_name, (u_long)(sizeof(locname) - 1));
fprintf(stderr, "%s%s: name exceeds %zu char\n",
locname, dp->d_name, sizeof(locname) - 1);
} else {
(void) strncat(locname, dp->d_name, (int)dp->d_namlen);
locname[namelen + dp->d_namlen] = '\0';
(void)strlcat(locname, dp->d_name, sizeof(locname));
treescan(locname, dp->d_ino, todo);
rst_seekdir(dirp, bpt, itp->t_seekpt);
}
@ -337,13 +336,13 @@ searchdir(ino_t inum, char *name)
* Put the directory entries in the directory file
*/
static void
putdir(char *buf, long size)
putdir(char *buf, size_t size)
{
struct direct cvtbuf;
struct odirect *odp;
struct odirect *eodp;
struct direct *dp;
long loc, i;
size_t loc, i;
if (cvtflag) {
eodp = (struct odirect *)&buf[size];
@ -417,7 +416,8 @@ putent(struct direct *dp)
if (dirloc + dp->d_reclen > DIRBLKSIZ) {
((struct direct *)(dirbuf + prev))->d_reclen =
DIRBLKSIZ - prev;
(void) fwrite(dirbuf, 1, DIRBLKSIZ, df);
if (fwrite(dirbuf, DIRBLKSIZ, 1, df) != 1)
fail_dirtmp(dirfile);
dirloc = 0;
}
memmove(dirbuf + dirloc, dp, (long)dp->d_reclen);
@ -432,7 +432,8 @@ static void
flushent(void)
{
((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
(void) fwrite(dirbuf, (int)dirloc, 1, df);
if (fwrite(dirbuf, (int)dirloc, 1, df) != 1)
fail_dirtmp(dirfile);
seekpt = ftell(df);
dirloc = 0;
}
@ -452,6 +453,17 @@ dcvt(struct odirect *odp, struct direct *ndp)
ndp->d_reclen = UFS_DIRSIZ(0, ndp, 0);
}
/*
* Save extended attributes for a directory entry to a file.
*/
static void
putdirattrs(char *buf, size_t size)
{
if (mf != NULL && fwrite(buf, size, 1, mf) != 1)
fail_dirtmp(modefile);
}
/*
* Seek to an entry in a directory.
* Only values returned by rst_telldir should be passed to rst_seekdir.
@ -582,15 +594,15 @@ opendirfile(const char *name)
void
setdirmodes(int flags)
{
FILE *mf;
struct modeinfo node;
struct entry *ep;
char *cp;
char *cp, *buf;
int bufsize;
vprintf(stdout, "Set directory mode, owner, and times.\n");
if (command == 'r' || command == 'R')
(void) snprintf(modefile, sizeof(modefile), "%s/rstmode%d",
tmpdir, (int)dumpdate);
(void) snprintf(modefile, sizeof(modefile), "%s/rstmode%jd",
tmpdir, (intmax_t)dumpdate);
if (modefile[0] == '#') {
panic("modefile not defined\n");
fprintf(stderr, "directory mode, owner, and times not set\n");
@ -604,10 +616,47 @@ setdirmodes(int flags)
return;
}
clearerr(mf);
bufsize = 0;
buf = NULL;
for (;;) {
(void) fread((char *)&node, 1, sizeof(struct modeinfo), mf);
if (ferror(mf)) {
warn("%s: cannot read modefile.", modefile);
fprintf(stderr, "Mode, owner, and times not set.\n");
break;
}
if (feof(mf))
break;
if (node.extsize > 0) {
if (bufsize < node.extsize) {
if (bufsize > 0)
free(buf);
if ((buf = malloc(node.extsize)) != NULL) {
bufsize = node.extsize;
} else {
bufsize = 0;
}
}
if (bufsize >= node.extsize) {
(void) fread(buf, 1, node.extsize, mf);
if (ferror(mf)) {
warn("%s: cannot read modefile.",
modefile);
fprintf(stderr, "Not all external ");
fprintf(stderr, "attributes set.\n");
break;
}
} else {
(void) fseek(mf, node.extsize, SEEK_CUR);
if (ferror(mf)) {
warn("%s: cannot seek in modefile.",
modefile);
fprintf(stderr, "Not all directory ");
fprintf(stderr, "attributes set.\n");
break;
}
}
}
ep = lookupino(node.ino);
if (command == 'i' || command == 'x') {
if (ep == NULL)
@ -620,11 +669,20 @@ setdirmodes(int flags)
continue;
}
if (ep == NULL) {
panic("cannot find directory inode %llu\n",
(unsigned long long)node.ino);
} else {
panic("cannot find directory inode %ju\n",
(uintmax_t)node.ino);
continue;
}
if (!Nflag) {
cp = myname(ep);
if (node.extsize > 0) {
if (bufsize >= node.extsize) {
set_extattr(-1, cp, buf, node.extsize, SXA_FILE);
} else {
fprintf(stderr, "Cannot restore %s%s\n",
"extended attributes for ", cp);
}
}
(void) utimens(cp, node.ctimep);
(void) utimens(cp, node.mtimep);
(void) chown(cp, node.uid, node.gid);
@ -638,9 +696,8 @@ setdirmodes(int flags)
}
ep->e_flags &= ~NEW;
}
}
if (ferror(mf))
panic("error setting directory modes\n");
if (bufsize > 0)
free(buf);
(void) fclose(mf);
}
@ -656,8 +713,8 @@ genliteraldir(const char *name, ino_t ino)
itp = inotablookup(ino);
if (itp == NULL)
panic("Cannot find directory inode %llu named %s\n",
(unsigned long long)ino, name);
panic("Cannot find directory inode %ju named %s\n",
(uintmax_t)ino, name);
if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
fprintf(stderr, "%s: ", name);
(void) fflush(stderr);
@ -667,18 +724,18 @@ genliteraldir(const char *name, ino_t ino)
rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
dp = dup(dirp->dd_fd);
for (i = itp->t_size; i > 0; i -= BUFSIZ) {
size = i < BUFSIZ ? i : BUFSIZ;
size = MIN(i, BUFSIZ);
if (read(dp, buf, (int) size) == -1) {
fprintf(stderr,
"write error extracting inode %llu, name %s\n",
(unsigned long long)curfile.ino, curfile.name);
"write error extracting inode %ju, name %s\n",
(uintmax_t)curfile.ino, curfile.name);
fprintf(stderr, "read: %s\n", strerror(errno));
exit(1);
}
if (!Nflag && write(ofile, buf, (int) size) == -1) {
fprintf(stderr,
"write error extracting inode %llu, name %s\n",
(unsigned long long)curfile.ino, curfile.name);
"write error extracting inode %ju, name %s\n",
(uintmax_t)curfile.ino, curfile.name);
fprintf(stderr, "write: %s\n", strerror(errno));
exit(1);
}
@ -707,14 +764,14 @@ inodetype(ino_t ino)
* If requested, save its pertinent mode, owner, and time info.
*/
static struct inotab *
allocinotab(FILE *mf, struct context *ctxp, long aseekpt)
allocinotab(struct context *ctxp, long aseekpt)
{
struct inotab *itp;
struct modeinfo node;
itp = calloc(1, sizeof(struct inotab));
if (itp == NULL)
panic("no memory directory table\n");
panic("no memory for directory table\n");
itp->t_next = inotab[INOHASH(ctxp->ino)];
inotab[INOHASH(ctxp->ino)] = itp;
itp->t_ino = ctxp->ino;
@ -730,11 +787,13 @@ allocinotab(FILE *mf, struct context *ctxp, long aseekpt)
node.ctimep[0].tv_nsec = ctxp->atime_nsec;
node.ctimep[1].tv_sec = ctxp->birthtime_sec;
node.ctimep[1].tv_nsec = ctxp->birthtime_nsec;
node.extsize = ctxp->extsize;
node.mode = ctxp->mode;
node.flags = ctxp->file_flags;
node.uid = ctxp->uid;
node.gid = ctxp->gid;
(void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf);
if (fwrite((char *)&node, sizeof(struct modeinfo), 1, mf) != 1)
fail_dirtmp(modefile);
return (itp);
}
@ -760,8 +819,28 @@ cleanup(void)
{
closemt();
if (modefile[0] != '#')
if (modefile[0] != '#') {
(void) truncate(modefile, 0);
(void) unlink(modefile);
if (dirfile[0] != '#')
}
if (dirfile[0] != '#') {
(void) truncate(dirfile, 0);
(void) unlink(dirfile);
}
}
/*
* Print out information about the failure to save directory,
* extended attribute, and mode information.
*/
static void
fail_dirtmp(char *filename)
{
warn("%s: cannot write directory database", filename);
if (errno == ENOSPC) {
fprintf(stderr, "Try making space in %s, %s\n%s\n", tmpdir,
"or set environment variable TMPDIR",
"to an alternate location with more disk space.");
}
exit(1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.15 2008/02/16 17:58:01 matt Exp $ */
/* $NetBSD: extern.h,v 1.16 2021/06/19 13:56:35 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -35,7 +35,7 @@ struct entry *addentry(const char *, ino_t, int);
long addfile(const char *, ino_t, int);
int addwhiteout(char *);
void badentry(struct entry *, const char *);
void canon(const char *, char *);
void canon(const char *, char *, size_t);
void checkrestore(void);
void cleanup(void);
void closemt(void);
@ -57,7 +57,8 @@ void freeentry(struct entry *);
void freename(char *);
int genliteraldir(const char *, ino_t);
char *gentempname(struct entry *);
void getfile(void (*)(char *, long), void (*)(char *, long));
void getfile(void (*)(char *, size_t),
void (*)(char *, size_t), void (*)(char *, size_t));
void getvol(int);
void initsymtable(const char *);
int inodetype(ino_t);
@ -91,6 +92,12 @@ struct direct *rst_readdir(RST_DIR *);
void rst_closedir(RST_DIR *);
void runcmdshell(void);
char *savename(const char *);
enum set_extattr_mode {
SXA_FILE,
SXA_LINK,
SXA_FD,
};
void set_extattr(int, char *, void *, int, enum set_extattr_mode);
void setdirmodes(int);
void setinput(const char *);
void setup(void);
@ -104,7 +111,7 @@ ino_t upperbnd(ino_t);
long verifyfile(const char *, ino_t, int);
void writemtree(const char *, const char *, const uid_t,
const gid_t, const mode_t, const u_long);
void xtrnull(char *, long);
void xtrnull(char *, size_t);
/* From ../dump/dumprmt.c */
void rmtclose(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: interactive.c,v 1.28 2019/02/03 03:19:26 mrg Exp $ */
/* $NetBSD: interactive.c,v 1.29 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1985, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)interactive.c 8.5 (Berkeley) 5/1/95";
#else
__RCSID("$NetBSD: interactive.c,v 1.28 2019/02/03 03:19:26 mrg Exp $");
__RCSID("$NetBSD: interactive.c,v 1.29 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -49,6 +49,7 @@ __RCSID("$NetBSD: interactive.c,v 1.28 2019/02/03 03:19:26 mrg Exp $");
#include <setjmp.h>
#include <glob.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -85,7 +86,7 @@ struct arglist {
static char *copynext(char *, char *);
static int fcmp(const void *, const void *);
static void formatf(struct afile *, int);
static void getcmd(char *, char *, char *, struct arglist *);
static void getcmd(char *, char *, char *, size_t, struct arglist *);
struct dirent *glob_readdir(RST_DIR *dirp);
static int glob_stat(const char *, struct stat *);
static void mkentry(char *, struct direct *, struct afile *);
@ -112,7 +113,7 @@ runcmdshell(void)
arglist.glob.gl_closedir = (void *)rst_closedir;
arglist.glob.gl_lstat = glob_stat;
arglist.glob.gl_stat = glob_stat;
canon("/", curdir);
canon("/", curdir, sizeof(curdir));
loop:
if (setjmp(reset) != 0) {
if (arglist.freeglob != 0) {
@ -124,7 +125,7 @@ loop:
volno = 0;
}
runshell = 1;
getcmd(curdir, cmd, name, &arglist);
getcmd(curdir, cmd, name, sizeof(name), &arglist);
switch (cmd[0]) {
/*
* Add elements to the extraction list.
@ -307,11 +308,11 @@ loop:
* eliminate any embedded ".." components.
*/
static void
getcmd(char *curdir, char *cmd, char *name, struct arglist *ap)
getcmd(char *curdir, char *cmd, char *name, size_t size, struct arglist *ap)
{
char *cp;
static char input[BUFSIZ];
char output[BUFSIZ];
char output[BUFSIZ * 2];
int globretval;
# define rawname input /* save space by reusing input buffer */
@ -331,7 +332,7 @@ getcmd(char *curdir, char *cmd, char *name, struct arglist *ap)
(void) fgets(input, BUFSIZ, terminal);
} while (!feof(terminal) && input[0] == '\n');
if (feof(terminal)) {
(void) strcpy(cmd, "quit");
(void) strlcpy(cmd, "quit", size);
return;
}
for (cp = &input[strlen(input) - 2]; *cp == ' ' || *cp == '\t'; cp--)
@ -346,7 +347,7 @@ getcmd(char *curdir, char *cmd, char *name, struct arglist *ap)
* If no argument, use curdir as the default.
*/
if (*cp == '\0') {
(void) strcpy(name, curdir);
(void) strlcpy(name, curdir, size);
return;
}
nextarg = cp;
@ -363,16 +364,14 @@ getnext:
* If it is an absolute pathname, canonicalize it and return it.
*/
if (rawname[0] == '/') {
canon(rawname, name);
canon(rawname, name, size);
} else {
/*
* For relative pathnames, prepend the current directory to
* it then canonicalize and return it.
*/
(void) strcpy(output, curdir);
(void) strcat(output, "/");
(void) strcat(output, rawname);
canon(output, name);
snprintf(output, sizeof(output), "%s/%s", curdir, rawname);
canon(output, name, sizeof(name));
}
if ((globretval = glob(name, GLOB_ALTDIRFUNC, NULL, &ap->glob)) < 0) {
fprintf(stderr, "%s: %s: ", ap->cmd, name);
@ -397,7 +396,7 @@ getnext:
ap->argcnt = ap->glob.gl_pathc;
retnext:
strcpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt]);
strlcpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt], size);
if (--ap->argcnt == 0) {
ap->freeglob = 0;
globfree(&ap->glob);
@ -458,7 +457,7 @@ copynext(char *input, char *output)
* remove any imbedded "." and ".." components.
*/
void
canon(const char *rawname, char *canonname)
canon(const char *rawname, char *canonname, size_t len)
{
char *cp, *np;
@ -468,6 +467,11 @@ canon(const char *rawname, char *canonname)
(void) strcpy(canonname, ".");
else
(void) strcpy(canonname, "./");
if (strlen(canonname) + strlen(rawname) >= len) {
fprintf(stderr, "canonname: not enough buffer space\n");
exit(1);
}
(void) strcat(canonname, rawname);
/*
* Eliminate multiple and trailing '/'s
@ -546,9 +550,7 @@ printlist(char *name, char *basename)
fprintf(stderr, "%s:\n", name);
entries = 0;
listp = list;
(void) strncpy(locname, name, MAXPATHLEN);
(void) strncat(locname, "/", MAXPATHLEN);
namelen = strlen(locname);
namelen = snprintf(locname, sizeof(locname), "%s/", name);
while ((dp = rst_readdir(dirp)) != NULL) {
if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)
continue;
@ -561,8 +563,7 @@ printlist(char *name, char *basename)
fprintf(stderr, "%s%s: name exceeds %d char\n",
locname, dp->d_name, MAXPATHLEN);
} else {
(void) strncat(locname, dp->d_name,
(int)dp->d_namlen);
(void)strlcat(locname, dp->d_name, MAXPATHLEN);
mkentry(locname, dp, listp++);
entries++;
}
@ -596,7 +597,7 @@ mkentry(char *name, struct direct *dp, struct afile *fp)
fp->fnum = dp->d_ino;
fp->fname = savename(dp->d_name);
for (cp = fp->fname; *cp; cp++)
if (!vflag && (*cp < ' ' || *cp >= 0177))
if (!vflag && isprint((unsigned char)*cp))
*cp = '?';
fp->len = cp - fp->fname;
if (dflag && TSTINO(fp->fnum, dumpmap) == 0)
@ -610,7 +611,7 @@ mkentry(char *name, struct direct *dp, struct afile *fp)
default:
fprintf(stderr, "Warning: undefined file type %d\n",
dp->d_type);
/* fall through */
/* FALLTHROUGH */
case DT_REG:
fp->postfix = ' ';
break;
@ -690,8 +691,8 @@ formatf(struct afile *list, int nentry)
for (j = 0; j < columns; j++) {
fp = &list[j * lines + i];
if (vflag) {
fprintf(stderr, "%*llu ", precision,
(unsigned long long)fp->fnum);
fprintf(stderr, "%*ju ", precision,
(uintmax_t)fp->fnum);
fp->len += precision + 1;
}
if (haveprefix) {
@ -767,7 +768,7 @@ glob_stat(const char *name, struct stat *stp)
static int
fcmp(const void *f1, const void *f2)
{
return (strcmp(((const struct afile *)f1)->fname,
return (strcoll(((const struct afile *)f1)->fname,
((const struct afile *)f2)->fname));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.36 2020/04/05 15:25:40 joerg Exp $ */
/* $NetBSD: main.c,v 1.37 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95";
#else
__RCSID("$NetBSD: main.c,v 1.36 2020/04/05 15:25:40 joerg Exp $");
__RCSID("$NetBSD: main.c,v 1.37 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -268,7 +268,7 @@ main(int argc, char *argv[])
extractdirs(0);
initsymtable((char *)0);
while (argc--) {
canon(*argv++, name);
canon(*argv++, name, sizeof(name));
ino = dirlookup(name);
if (ino == 0)
continue;
@ -283,7 +283,7 @@ main(int argc, char *argv[])
extractdirs(1);
initsymtable((char *)0);
while (argc--) {
canon(*argv++, name);
canon(*argv++, name, sizeof(name));
ino = dirlookup(name);
if (ino == 0)
continue;

View File

@ -1,4 +1,4 @@
/* $NetBSD: restore.c,v 1.21 2013/01/22 09:39:13 dholland Exp $ */
/* $NetBSD: restore.c,v 1.22 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)restore.c 8.3 (Berkeley) 9/13/94";
#else
__RCSID("$NetBSD: restore.c,v 1.21 2013/01/22 09:39:13 dholland Exp $");
__RCSID("$NetBSD: restore.c,v 1.22 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -63,7 +63,7 @@ listfile(const char *name, ino_t ino, int type)
if (TSTINO(ino, dumpmap) == 0)
return (descend);
vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
fprintf(stdout, "%10llu\t%s\n", (unsigned long long)ino, name);
fprintf(stdout, "%10ju\t%s\n", (uintmax_t)ino, name);
return (descend);
}
@ -85,8 +85,8 @@ addfile(const char *name, ino_t ino, int type)
if (ino == UFS_WINO && command == 'i' && !vflag)
return (descend);
if (!mflag) {
(void) snprintf(buf, sizeof(buf), "./%llu",
(unsigned long long)ino);
(void) snprintf(buf, sizeof(buf), "./%ju",
(uintmax_t)ino);
name = buf;
if (type == NODE) {
(void) genliteraldir(name, ino);
@ -322,7 +322,7 @@ nodeupdates(const char *name, ino_t ino, int type)
} else {
mktempname(np);
}
/* fall through */
/* FALLTHROUGH */
/*
* A previously non-existent file.
@ -353,7 +353,7 @@ nodeupdates(const char *name, ino_t ino, int type)
case ONTAPE|INOFND:
if (type == LEAF && (ip->e_flags & KEEP) == 0)
ip->e_flags |= EXTRACT;
/* fall through */
/* FALLTHROUGH */
case INOFND:
if ((ip->e_flags & KEEP) == 0) {
renameit(myname(ip), name);
@ -461,8 +461,8 @@ nodeupdates(const char *name, ino_t ino, int type)
* next incremental tape.
*/
case 0:
fprintf(stderr, "%s: (inode %llu) not found on tape\n",
name, (unsigned long long)ino);
fprintf(stderr, "%s: (inode %ju) not found on tape\n",
name, (uintmax_t)ino);
break;
/*
@ -616,8 +616,8 @@ createleaves(const char *symtabfile)
while (first < curfile.ino) {
ep = lookupino(first);
if (ep == NULL)
panic("%llu: bad first\n",
(unsigned long long)first);
panic("%ju: bad first\n",
(uintmax_t)first);
fprintf(stderr, "%s: not found on tape\n", myname(ep));
ep->e_flags &= ~(NEW|EXTRACT);
first = lowerbnd(first);
@ -630,9 +630,9 @@ createleaves(const char *symtabfile)
* on the next incremental tape.
*/
if (first != curfile.ino) {
fprintf(stderr, "expected next file %llu, got %llu\n",
(unsigned long long)first,
(unsigned long long)curfile.ino);
fprintf(stderr, "expected next file %ju, got %ju\n",
(uintmax_t)first,
(uintmax_t)curfile.ino);
skipfile();
goto next;
}
@ -854,7 +854,7 @@ verifyfile(const char *name, ino_t ino, int type)
if (np == ep)
break;
if (np == NULL)
panic("missing inumber %llu\n", (unsigned long long)ino);
panic("missing inumber %ju\n", (uintmax_t)ino);
if (ep->e_type == LEAF && type != LEAF)
badentry(ep, "type should be LEAF");
return (descend);

View File

@ -1,4 +1,4 @@
/* $NetBSD: restore.h,v 1.22 2020/04/05 15:25:40 joerg Exp $ */
/* $NetBSD: restore.h,v 1.23 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -134,6 +134,7 @@ extern struct context {
int atime_nsec; /* access time nanoseconds */
int mtime_nsec; /* modified time nanoseconds */
int birthtime_nsec; /* creation time nanoseconds */
int extsize; /* size of extended attribute data */
off_t size; /* size of file */
const char *name; /* name of file */
} curfile;

View File

@ -1,4 +1,4 @@
/* $NetBSD: symtab.c,v 1.29 2013/01/22 09:39:13 dholland Exp $ */
/* $NetBSD: symtab.c,v 1.30 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: symtab.c,v 1.29 2013/01/22 09:39:13 dholland Exp $");
__RCSID("$NetBSD: symtab.c,v 1.30 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -102,7 +102,7 @@ addino(ino_t inum, struct entry *np)
struct entry **epp;
if (inum < UFS_WINO || inum >= maxino)
panic("addino: out of range %llu\n", (unsigned long long)inum);
panic("addino: out of range %ju\n", (uintmax_t)inum);
epp = &entry[inum % entrytblsize];
np->e_ino = inum;
np->e_next = *epp;
@ -123,8 +123,8 @@ deleteino(ino_t inum)
struct entry **prev;
if (inum < UFS_WINO || inum >= maxino)
panic("deleteino: out of range %llu\n",
(unsigned long long)inum);
panic("deleteino: out of range %ju\n",
(uintmax_t)inum);
prev = &entry[inum % entrytblsize];
for (next = *prev; next != NULL; next = next->e_next) {
if (next->e_ino == inum) {
@ -134,7 +134,7 @@ deleteino(ino_t inum)
}
prev = &next->e_next;
}
panic("deleteino: %llu not found\n", (unsigned long long)inum);
panic("deleteino: %ju not found\n", (uintmax_t)inum);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: tape.c,v 1.70 2021/03/11 01:13:11 msaitoh Exp $ */
/* $NetBSD: tape.c,v 1.71 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
#else
__RCSID("$NetBSD: tape.c,v 1.70 2021/03/11 01:13:11 msaitoh Exp $");
__RCSID("$NetBSD: tape.c,v 1.71 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -48,7 +48,11 @@ __RCSID("$NetBSD: tape.c,v 1.70 2021/03/11 01:13:11 msaitoh Exp $");
#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <sys/stat.h>
#include <sys/extattr.h>
#define _ACL_PRIVATE
#include <sys/acl.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/dinode.h>
#include <protocols/dumprestore.h>
@ -109,6 +113,9 @@ static union digest_context {
#define FLUSHTAPEBUF() blkcnt = ntrec + 1
const char *namespace_names[] = EXTATTR_NAMESPACE_NAMES;
union u_ospcl {
char dummy[TP_BSIZE];
struct s_ospcl {
@ -141,15 +148,18 @@ static void accthdr(struct s_spcl *);
static int checksum(int *);
static void findinode(struct s_spcl *);
static void findtapeblksize(void);
static char *setupextattr(size_t);
static void xtrattr(char *, size_t);
static void skiphole(void (*)(char *, size_t), volatile size_t *);
static void getbitmap(char **);
static int gethead(struct s_spcl *);
static void readtape(char *);
static void setdumpnum(void);
static void terminateinput(void);
static void xtrfile(char *, long);
static void xtrlnkfile(char *, long);
__dead static void xtrlnkskip(char *, long);
static void xtrskip(char *, long);
static void xtrfile(char *, size_t);
static void xtrlnkfile(char *, size_t);
__dead static void xtrlnkskip(char *, size_t);
static void xtrskip(char *, size_t);
static void swap_header(struct s_spcl *);
static void swap_old_header(struct s_ospcl *);
@ -620,13 +630,15 @@ int
extractfile(char *name)
{
char dbuffer[DIGEST_BUFFER_SIZE];
int flags;
u_int flags;
uid_t uid;
gid_t gid;
mode_t mode;
int extsize;
struct timespec mtimep[2], ctimep[2];
struct entry *ep;
int setbirth;
char *buf;
curfile.name = name;
curfile.action = USING;
@ -643,6 +655,7 @@ extractfile(char *name)
ctimep[1].tv_sec = curfile.birthtime_sec;
ctimep[1].tv_nsec = curfile.birthtime_nsec;
}
extsize = curfile.extsize;
uid = curfile.uid;
gid = curfile.gid;
mode = curfile.mode;
@ -673,7 +686,8 @@ extractfile(char *name)
case IFLNK:
lnkbuf[0] = '\0';
pathlen = 0;
getfile(xtrlnkfile, xtrlnkskip);
buf = setupextattr(extsize);
getfile(xtrlnkfile, xtrattr, xtrlnkskip);
if (pathlen == 0) {
vprintf(stdout,
"%s: zero length symbolic link (ignored)\n", name);
@ -682,6 +696,8 @@ extractfile(char *name)
if (uflag)
(void) unlink(name);
if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
if (extsize > 0)
set_extattr(-1, name, buf, extsize, SXA_LINK);
if (setbirth)
(void) lutimens(name, ctimep);
(void) lutimens(name, mtimep);
@ -712,7 +728,13 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
if (extsize == 0) {
skipfile();
} else {
buf = setupextattr(extsize);
getfile(xtrnull, xtrattr, xtrnull);
set_extattr(-1, name, buf, extsize, SXA_FILE);
}
if (setbirth)
(void) utimens(name, ctimep);
(void) utimens(name, mtimep);
@ -741,7 +763,13 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
if (extsize == 0) {
skipfile();
} else {
buf = setupextattr(extsize);
getfile(xtrnull, xtrattr, xtrnull);
set_extattr(-1, name, buf, extsize, SXA_FILE);
}
if (setbirth)
(void) utimens(name, ctimep);
(void) utimens(name, mtimep);
@ -767,7 +795,10 @@ extractfile(char *name)
}
if (Dflag)
(*ddesc->dd_init)(&dcontext);
getfile(xtrfile, xtrskip);
buf = setupextattr(extsize);
getfile(xtrfile, xtrattr, xtrskip);
if (extsize > 0)
set_extattr(ofile, name, buf, extsize, SXA_FD);
if (Dflag) {
(*ddesc->dd_end)(&dcontext, dbuffer);
for (ep = lookupname(name); ep != NULL;
@ -794,6 +825,127 @@ extractfile(char *name)
/* NOTREACHED */
}
/*
* Set attributes on a file descriptor, link, or file.
*/
void
set_extattr(int fd, char *name, void *buf, int size, enum set_extattr_mode mode)
{
struct extattr *eap, *eaend;
const char *method;
ssize_t res;
int error;
char eaname[EXTATTR_MAXNAMELEN + 1];
vprintf(stdout, "Set attributes for %s:", name);
eaend = (void *)((char *)buf + size);
for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
/*
* Make sure this entry is complete.
*/
if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
dprintf(stdout, "\n\t%scorrupted",
eap == buf ? "" : "remainder ");
break;
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
continue;
snprintf(eaname, sizeof(eaname), "%.*s",
(int)eap->ea_namelength, eap->ea_name);
vprintf(stdout, "\n\t%s, (%d bytes), %s",
namespace_names[eap->ea_namespace], eap->ea_length,
eaname);
/*
* First we try the general attribute setting interface.
* However, some attributes can only be set by root or
* by using special interfaces (for example, ACLs).
*/
switch (mode) {
case SXA_FD:
res = extattr_set_fd(fd, eap->ea_namespace,
eaname, EXTATTR_CONTENT(eap),
EXTATTR_CONTENT_SIZE(eap));
method = "extattr_set_fd";
break;
case SXA_LINK:
res = extattr_set_link(name, eap->ea_namespace,
eaname, EXTATTR_CONTENT(eap),
EXTATTR_CONTENT_SIZE(eap));
method = "extattr_set_link";
break;
case SXA_FILE:
res = extattr_set_file(name, eap->ea_namespace,
eaname, EXTATTR_CONTENT(eap),
EXTATTR_CONTENT_SIZE(eap));
method = "extattr_set_file";
break;
default:
abort();
}
if (res != -1) {
dprintf(stdout, " (set using %s)", method);
continue;
}
/*
* If the general interface refuses to set the attribute,
* then we try all the specialized interfaces that we
* know about.
*/
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
strcmp(eaname, POSIX1E_ACL_ACCESS_EXTATTR_NAME) == 0) {
switch (mode) {
case SXA_FD:
error = acl_set_fd(fd, EXTATTR_CONTENT(eap));
method = "acl_set_fd";
break;
case SXA_LINK:
error = acl_set_link_np(name, ACL_TYPE_ACCESS,
EXTATTR_CONTENT(eap));
method = "acl_set_link_np";
break;
case SXA_FILE:
error = acl_set_file(name, ACL_TYPE_ACCESS,
EXTATTR_CONTENT(eap));
method = "acl_set_file";
break;
default:
abort();
}
if (error != -1) {
dprintf(stdout, " (set using %s)", method);
continue;
}
}
if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
strcmp(eaname, POSIX1E_ACL_DEFAULT_EXTATTR_NAME) == 0) {
switch (mode) {
case SXA_FD:
error = acl_set_fd(fd, EXTATTR_CONTENT(eap));
method = "acl_set_fd";
break;
case SXA_LINK:
error = acl_set_link_np(name, ACL_TYPE_DEFAULT,
EXTATTR_CONTENT(eap));
method = "acl_set_link_np";
break;
case SXA_FILE:
error = acl_set_file(name, ACL_TYPE_DEFAULT,
EXTATTR_CONTENT(eap));
method = "acl_set_file";
break;
default:
abort();
}
if (error != -1) {
dprintf(stdout, " (set using %s)", method);
continue;
}
}
vprintf(stdout, " (unable to set)");
}
vprintf(stdout, "\n");
}
/*
* skip over bit maps on the tape
*/
@ -813,7 +965,22 @@ skipfile(void)
{
curfile.action = SKIP;
getfile(xtrnull, xtrnull);
getfile(xtrnull, xtrnull, xtrnull);
}
/*
* Skip a hole in an output file
*/
static void
skiphole(void (*skip)(char *, size_t), volatile size_t *seekpos)
{
char buf[MAXBSIZE];
size_t s = *seekpos;
if (s > 0) {
(*skip)(buf, s);
*seekpos = 0;
}
}
/*
@ -870,18 +1037,21 @@ loop:
* to the skip function.
*/
void
getfile(void (*fill)(char *buf, long size),
void (*skip)(char *buf, long size))
getfile(void (*datafill)(char *, size_t), void (*attrfill)(char *, size_t),
void (*skip)(char *, size_t))
{
int i;
int volatile curblk;
quad_t volatile size;
static char clearedbuf[MAXBSIZE];
volatile off_t size;
volatile size_t seekpos;
volatile int curblk, attrsize;
void (*fillit)(char *, size_t);
char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
char junk[TP_BSIZE];
curblk = 0;
size = spcl.c_size;
seekpos = 0;
attrsize = spcl.c_extsize;
if (spcl.c_type == TS_END)
panic("ran off end of tape\n");
@ -890,26 +1060,54 @@ getfile(void (*fill)(char *buf, long size),
if (!gettingfile && setjmp(restart) != 0)
return;
gettingfile++;
fillit = datafill;
if (size == 0 && attrsize > 0) {
fillit = attrfill;
size = attrsize;
attrsize = 0;
}
loop:
for (i = 0; i < spcl.c_count; i++) {
if (spcl.c_addr[i]) {
readtape(&buf[curblk++][0]);
if ((uint32_t)curblk == fssize / TP_BSIZE) {
(*fill)((char *)buf, (long)(size > TP_BSIZE ?
skiphole(skip, &seekpos);
(*fillit)((char *)buf, (long)(size > TP_BSIZE ?
fssize : (curblk - 1) * TP_BSIZE + size));
curblk = 0;
}
} else {
if (curblk > 0) {
(*fill)((char *)buf, (long)(size > TP_BSIZE ?
skiphole(skip, &seekpos);
(*fillit)((char *)buf, (long)(size > TP_BSIZE ?
curblk * TP_BSIZE :
(curblk - 1) * TP_BSIZE + size));
curblk = 0;
}
(*skip)(clearedbuf, (long)(size > TP_BSIZE ?
TP_BSIZE : size));
/*
* We have a block of a hole. Don't skip it
* now, because there may be next adjacent
* block of the hole in the file. Postpone the
* seek until next file write.
*/
seekpos += (long)MIN(TP_BSIZE, size);
}
if ((size -= TP_BSIZE) <= 0) {
if (size > -TP_BSIZE && curblk > 0) {
skiphole(skip, &seekpos);
(*fillit)((char *)buf,
(long)((curblk * TP_BSIZE) + size));
curblk = 0;
}
if (attrsize > 0) {
fillit = attrfill;
size = attrsize;
attrsize = 0;
continue;
}
if (spcl.c_count - i > 1)
dprintf(stdout, "skipping %d junk block(s)\n",
spcl.c_count - i - 1);
for (i++; i < spcl.c_count; i++)
if (spcl.c_addr[i])
readtape(junk);
@ -924,7 +1122,7 @@ loop:
curfile.name, blksread);
}
if (curblk > 0)
(*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size));
panic("getfile: lost data\n");
/* Skip over Linux extended attributes. */
if (spcl.c_type == TS_INODE && (spcl.c_flags & DR_EXTATTRIBUTES)) {
for (i = 0; i < spcl.c_count; i++)
@ -935,11 +1133,55 @@ loop:
gettingfile = 0;
}
/*
* These variables are shared between the next two functions.
*/
static size_t extbufsize = 0;
static char *extbuf;
static size_t extloc;
/*
* Allocate a buffer into which to extract extended attributes.
*/
static char *
setupextattr(size_t extsize)
{
extloc = 0;
if (extsize <= extbufsize)
return (extbuf);
if (extbufsize > 0)
free(extbuf);
if ((extbuf = malloc(extsize)) != NULL) {
extbufsize = extsize;
return (extbuf);
}
extbufsize = 0;
extbuf = NULL;
fprintf(stderr, "Cannot extract %zu bytes %s for inode %ju, name %s\n",
extsize, "of extended attributes", (uintmax_t)curfile.ino,
curfile.name);
return (NULL);
}
/*
* Extract the next block of extended attributes.
*/
static void
xtrattr(char *buf, size_t size)
{
if (extloc + size > extbufsize)
panic("overrun attribute buffer\n");
memmove(&extbuf[extloc], buf, size);
extloc += size;
}
/*
* Write out the next block of a file.
*/
static void
xtrfile(char *buf, long size)
xtrfile(char *buf, size_t size)
{
if (Dflag)
@ -948,8 +1190,8 @@ xtrfile(char *buf, long size)
return;
if (write(ofile, buf, (int) size) == -1) {
fprintf(stderr,
"write error extracting inode %llu, name %s\nwrite: %s\n",
(unsigned long long)curfile.ino, curfile.name,
"write error extracting inode %ju, name %s\nwrite: %s\n",
(uintmax_t)curfile.ino, curfile.name,
strerror(errno));
exit(1);
}
@ -960,7 +1202,7 @@ xtrfile(char *buf, long size)
*/
/* ARGSUSED */
static void
xtrskip(char *buf, long size)
xtrskip(char *buf, size_t size)
{
if (Dflag)
@ -969,8 +1211,8 @@ xtrskip(char *buf, long size)
return;
if (lseek(ofile, size, SEEK_CUR) == -1) {
fprintf(stderr,
"seek error extracting inode %llu, name %s\nlseek: %s\n",
(unsigned long long)curfile.ino, curfile.name,
"seek error extracting inode %ju, name %s\nlseek: %s\n",
(uintmax_t)curfile.ino, curfile.name,
strerror(errno));
exit(1);
}
@ -980,7 +1222,7 @@ xtrskip(char *buf, long size)
* Collect the next block of a symbolic link.
*/
static void
xtrlnkfile(char *buf, long size)
xtrlnkfile(char *buf, size_t size)
{
pathlen += size;
@ -997,7 +1239,7 @@ xtrlnkfile(char *buf, long size)
*/
/* ARGSUSED */
static void
xtrlnkskip(char *buf __unused, long size __unused)
xtrlnkskip(char *buf __unused, size_t size __unused)
{
fprintf(stderr, "unallocated block in symbolic link %s\n",
@ -1010,7 +1252,7 @@ xtrlnkskip(char *buf __unused, long size __unused)
*/
/* ARGSUSED */
void
xtrnull(char *buf __unused, long size __unused)
xtrnull(char *buf __unused, size_t size __unused)
{
return;
@ -1092,8 +1334,8 @@ getmore:
fprintf(stderr, "restoring %s\n", curfile.name);
break;
case SKIP:
fprintf(stderr, "skipping over inode %llu\n",
(unsigned long long)curfile.ino);
fprintf(stderr, "skipping over inode %ju\n",
(uintmax_t)curfile.ino);
break;
}
if (!yflag && !reply("continue"))
@ -1274,6 +1516,7 @@ good:
buf->c_birthtime = 0;
buf->c_birthtimensec = 0;
buf->c_atimensec = buf->c_mtimensec = 0;
buf->c_extsize = 0;
}
case TS_ADDR:
@ -1330,12 +1573,12 @@ accthdr(struct s_spcl *header)
fprintf(stderr, "Used inodes map header");
break;
case TS_INODE:
fprintf(stderr, "File header, ino %llu",
(unsigned long long)previno);
fprintf(stderr, "File header, ino %ju",
(uintmax_t)previno);
break;
case TS_ADDR:
fprintf(stderr, "File continuation header, ino %llu",
(unsigned long long)previno);
fprintf(stderr, "File continuation header, ino %ju",
(uintmax_t)previno);
break;
case TS_END:
fprintf(stderr, "End of tape header");
@ -1417,6 +1660,7 @@ skip:
curfile.mtime_nsec = header->c_mtimensec;
curfile.birthtime_sec = header->c_birthtime;
curfile.birthtime_nsec = header->c_birthtimensec;
curfile.extsize = header->c_extsize;
curfile.size = header->c_size;
curfile.ino = header->c_inumber;
break;
@ -1468,8 +1712,8 @@ checksum(int *buf)
}
if (i != CHECKSUM) {
fprintf(stderr, "Checksum error %o, inode %llu file %s\n", i,
(unsigned long long)curfile.ino, curfile.name);
fprintf(stderr, "Checksum error %o, inode %ju file %s\n", i,
(uintmax_t)curfile.ino, curfile.name);
return(FAIL);
}
return(GOOD);
@ -1502,6 +1746,7 @@ swap_header(struct s_spcl *s)
s->c_checksum = bswap32(s->c_checksum);
s->c_mode = bswap16(s->c_mode);
s->c_extsize = bswap64(s->c_extsize);
s->c_size = bswap64(s->c_size);
s->c_old_atime = bswap32(s->c_old_atime);
s->c_atimensec = bswap32(s->c_atimensec);

View File

@ -1,4 +1,4 @@
/* $NetBSD: utilities.c,v 1.23 2013/01/22 09:39:13 dholland Exp $ */
/* $NetBSD: utilities.c,v 1.24 2021/06/19 13:56:35 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)utilities.c 8.5 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: utilities.c,v 1.23 2013/01/22 09:39:13 dholland Exp $");
__RCSID("$NetBSD: utilities.c,v 1.24 2021/06/19 13:56:35 christos Exp $");
#endif
#endif /* not lint */
@ -115,8 +115,8 @@ gentempname(struct entry *ep)
i++;
if (np == NULL)
badentry(ep, "not on ino list");
(void)snprintf(name, sizeof(name), "%s%ld%llu", TMPHDR, (long) i,
(unsigned long long)ep->e_ino);
(void)snprintf(name, sizeof(name), "%s%ld%ju", TMPHDR, (long) i,
(uintmax_t)ep->e_ino);
return (name);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: extattr.h,v 1.10 2020/05/16 18:31:53 christos Exp $ */
/* $NetBSD: extattr.h,v 1.11 2021/06/19 13:56:34 christos Exp $ */
/*-
* Copyright (c) 1999-2001 Robert N. M. Watson
@ -41,11 +41,27 @@
#include <sys/types.h>
#define EXTATTR_NAMESPACE_EMPTY 0x00000000
#define EXTATTR_NAMESPACE_EMPTY_STRING "empty"
#define EXTATTR_NAMESPACE_USER 0x00000001
#define EXTATTR_NAMESPACE_USER_STRING "user"
#define EXTATTR_NAMESPACE_SYSTEM 0x00000002
#define EXTATTR_NAMESPACE_SYSTEM_STRING "system"
/*
* The following macro is designed to initialize an array that maps
* extended-attribute namespace values to their names, e.g.:
*
* char *extattr_namespace_names[] = EXTATTR_NAMESPACE_NAMES;
*/
#define EXTATTR_NAMESPACE_NAMES { \
EXTATTR_NAMESPACE_EMPTY_STRING, \
EXTATTR_NAMESPACE_USER_STRING, \
EXTATTR_NAMESPACE_SYSTEM_STRING, \
}
#define EXTATTR_MAXNAMELEN KERNEL_NAME_MAX
/* for sys_extattrctl */
#define EXTATTR_CMD_START 0x00000001
#define EXTATTR_CMD_STOP 0x00000002
@ -57,7 +73,6 @@
/* VOP_LISTEXTATTR flags */
#define EXTATTR_LIST_LENPREFIX 1 /* names with length prefix */
#define EXTATTR_MAXNAMELEN KERNEL_NAME_MAX
struct lwp;
struct vnode;
int extattr_check_cred(struct vnode *, int, kauth_cred_t, int);