static char *sccsid
= "@(#)tar.c 4.15 (Berkeley) %G%";
union hblock tbuf
[NBLOCK
];
char tname
[] = "/tmp/tarXXXXXX";
char magtape
[] = "/dev/rmt8";
for (cp
= *argv
++; *cp
; cp
++)
"tar: tapefile must be specified with 'f' option\n");
if ((tfile
= fopen(tname
, "w")) == NULL
) {
"Tar: cannot create temporary file (%s)\n",
fprintf(tfile
, "!!!!!/!/!/!/!/!/!/! 000\n");
if (nblock
> NBLOCK
|| nblock
<= 0) {
fprintf(stderr
, "Invalid blocksize. (Max %d)\n",
fprintf(stderr
, "tar: %c: unknown option\n", *cp
);
if (!rflag
&& !xflag
&& !tflag
)
if (cflag
&& tfile
!= NULL
)
if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGQUIT
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGTERM
, SIG_IGN
) != SIG_IGN
)
if (strcmp(usefile
, "-") == 0) {
"Can only create standard output archives\n");
} else if ((mt
= open(usefile
, 2)) < 0) {
if (cflag
== 0 || (mt
= creat(usefile
, 0666)) < 0) {
"tar: cannot open %s\n", usefile
);
if (strcmp(usefile
, "-") == 0) {
} else if ((mt
= open(usefile
, 0)) < 0) {
fprintf(stderr
, "tar: cannot open %s\n", usefile
);
"tar: usage tar -{txruB}[cvfblmh] [tapefile] [blocksize] file1 file2...\n");
char wdir
[MAXPATHLEN
], tempdir
[MAXPATHLEN
], *parent
;
"sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s",
tname
, tname
, tname
, tname
, tname
, tname
);
freopen(tname
, "r", tfile
);
fstat(fileno(tfile
), &stbuf
);
while (*argv
&& ! term
) {
if (!strcmp(cp2
, "-C") && argv
[1]) {
for (cp
= *argv
; *cp
; cp
++)
parent
= getcwd(tempdir
);
putfile(*argv
++, cp2
, parent
);
for (; ihead
!= NULL
; ihead
= ihead
->nextp
) {
fprintf(stderr
, "Missing links to %s\n", ihead
->pathname
);
if (dblock
.dbuf
.name
[0] != '\0')
register struct stat
*sp
;
readtape((char *)&dblock
);
if (dblock
.dbuf
.name
[0] == '\0')
sscanf(dblock
.dbuf
.mode
, "%o", &i
);
sscanf(dblock
.dbuf
.uid
, "%o", &i
);
sscanf(dblock
.dbuf
.gid
, "%o", &i
);
sscanf(dblock
.dbuf
.size
, "%lo", &sp
->st_size
);
sscanf(dblock
.dbuf
.mtime
, "%lo", &sp
->st_mtime
);
sscanf(dblock
.dbuf
.chksum
, "%o", &chksum
);
if (chksum
!= (i
= checksum())) {
fprintf(stderr
, "directory checksum error (%d != %d)\n",
fprintf(tfile
, "%s %s\n", dblock
.dbuf
.name
, dblock
.dbuf
.mtime
);
if (dblock
.dbuf
.linkflag
== '1')
putfile(longname
, shortname
, parent
)
char newparent
[NAMSIZ
+64];
i
= lstat(shortname
, &stbuf
);
i
= stat(shortname
, &stbuf
);
fprintf(stderr
, "tar: %s: cannot open file\n", longname
);
fprintf(stderr
, "tar: %s: no such file or directory\n",
fprintf(stderr
, "tar: %s: cannot stat file\n", longname
);
if (tfile
!= NULL
&& checkupdate(longname
) == 0)
if (checkw('r', longname
) == 0)
if (Fflag
&& checkf(shortname
, stbuf
.st_mode
, Fflag
) == 0)
switch (stbuf
.st_mode
& S_IFMT
) {
for (i
= 0, cp
= buf
; *cp
++ = longname
[i
++];)
if ((cp
- buf
) >= NAMSIZ
) {
fprintf(stderr
, "%s: file name too long\n",
strcpy(dblock
.dbuf
.name
,buf
);
sprintf(dblock
.dbuf
.chksum
, "%6o", checksum());
writetape((char *)&dblock
);
sprintf(newparent
, "%s/%s", parent
, shortname
);
if ((dirp
= opendir(".")) == NULL
) {
fprintf(stderr
, "%s: directory read error\n", longname
);
while ((dp
= readdir(dirp
)) != NULL
&& !term
) {
if (!strcmp(".", dp
->d_name
) ||
!strcmp("..", dp
->d_name
))
putfile(buf
, cp
, newparent
);
if (strlen(longname
) >= NAMSIZ
) {
fprintf(stderr
, "%s: file name too long\n", longname
);
strcpy(dblock
.dbuf
.name
, longname
);
if (stbuf
.st_size
+ 1 >= NAMSIZ
) {
fprintf(stderr
, "%s: symbolic link too long\n",
i
= readlink(shortname
, dblock
.dbuf
.linkname
, NAMSIZ
- 1);
dblock
.dbuf
.linkname
[i
] = '\0';
dblock
.dbuf
.linkflag
= '2';
fprintf(stderr
, "a %s ", longname
);
fprintf(stderr
, "symbolic link to %s\n",
sprintf(dblock
.dbuf
.size
, "%11lo", 0);
sprintf(dblock
.dbuf
.chksum
, "%6o", checksum());
writetape((char *)&dblock
);
if ((infile
= open(shortname
, 0)) < 0) {
fprintf(stderr
, "tar: %s: cannot open file\n", longname
);
if (strlen(longname
) >= NAMSIZ
) {
fprintf(stderr
, "%s: file name too long\n", longname
);
strcpy(dblock
.dbuf
.name
, longname
);
if (stbuf
.st_nlink
> 1) {
for (lp
= ihead
; lp
!= NULL
; lp
= lp
->nextp
)
if (lp
->inum
== stbuf
.st_ino
&&
lp
->devnum
== stbuf
.st_dev
) {
strcpy(dblock
.dbuf
.linkname
, lp
->pathname
);
dblock
.dbuf
.linkflag
= '1';
sprintf(dblock
.dbuf
.chksum
, "%6o", checksum());
writetape( (char *) &dblock
);
fprintf(stderr
, "a %s ", longname
);
fprintf(stderr
, "link to %s\n", lp
->pathname
);
lp
= (struct linkbuf
*) malloc(sizeof(*lp
));
"Out of memory. Link information lost\n");
lp
->devnum
= stbuf
.st_dev
;
lp
->count
= stbuf
.st_nlink
- 1;
strcpy(lp
->pathname
, longname
);
blocks
= (stbuf
.st_size
+ (TBLOCK
-1)) / TBLOCK
;
fprintf(stderr
, "a %s ", longname
);
fprintf(stderr
, "%ld blocks\n", blocks
);
sprintf(dblock
.dbuf
.chksum
, "%6o", checksum());
writetape((char *)&dblock
);
while ((i
= read(infile
, buf
, TBLOCK
)) > 0 && blocks
> 0) {
if (blocks
!= 0 || i
!= 0)
fprintf(stderr
, "%s: file changed size\n", longname
);
fprintf(stderr
, "tar: %s is not a file. Not dumped\n",
for (cp
= argv
; *cp
; cp
++)
if (prefix(*cp
, dblock
.dbuf
.name
))
if (checkw('x', dblock
.dbuf
.name
) == 0) {
if ((s
= rindex(dblock
.dbuf
.name
, '/')) == 0)
if (checkf(s
, stbuf
.st_mode
, Fflag
) == 0) {
if (checkdir(dblock
.dbuf
.name
))
if (dblock
.dbuf
.linkflag
== '2') {
unlink(dblock
.dbuf
.name
);
if (symlink(dblock
.dbuf
.linkname
, dblock
.dbuf
.name
)<0) {
fprintf(stderr
, "%s: symbolic link failed\n",
fprintf(stderr
, "x %s symbolic link to %s\n",
dblock
.dbuf
.name
, dblock
.dbuf
.linkname
);
/* ignore alien orders */
chown(dblock
.dbuf
.name
, stbuf
.st_uid
, stbuf
.st_gid
);
timep
[1] = stbuf
.st_mtime
;
utime(dblock
.dbuf
.name
, timep
);
chmod(dblock
.dbuf
.name
, stbuf
.st_mode
& 07777);
if (dblock
.dbuf
.linkflag
== '1') {
unlink(dblock
.dbuf
.name
);
if (link(dblock
.dbuf
.linkname
, dblock
.dbuf
.name
) < 0) {
fprintf(stderr
, "%s: cannot link\n",
fprintf(stderr
, "%s linked to %s\n",
dblock
.dbuf
.name
, dblock
.dbuf
.linkname
);
if ((ofile
= creat(dblock
.dbuf
.name
,stbuf
.st_mode
&0xfff)) < 0) {
fprintf(stderr
, "tar: %s - cannot create\n",
chown(dblock
.dbuf
.name
, stbuf
.st_uid
, stbuf
.st_gid
);
blocks
= ((bytes
= stbuf
.st_size
) + TBLOCK
-1)/TBLOCK
;
fprintf(stderr
, "x %s, %ld bytes, %ld tape blocks\n",
dblock
.dbuf
.name
, bytes
, blocks
);
for (; blocks
-- > 0; bytes
-= TBLOCK
) {
if (write(ofile
, buf
, TBLOCK
) < 0) {
"tar: %s: HELP - extract write error\n",
if (write(ofile
, buf
, (int) bytes
) < 0) {
"tar: %s: HELP - extract write error\n",
timep
[1] = stbuf
.st_mtime
;
utime(dblock
.dbuf
.name
, timep
);
chmod(dblock
.dbuf
.name
, stbuf
.st_mode
& 07777);
printf("%s", dblock
.dbuf
.name
);
if (dblock
.dbuf
.linkflag
== '1')
printf(" linked to %s", dblock
.dbuf
.linkname
);
if (dblock
.dbuf
.linkflag
== '2')
printf(" symbolic link to %s", dblock
.dbuf
.linkname
);
for (cp
= buf
; cp
< &buf
[TBLOCK
]; )
register struct stat
*st
;
printf("%3d/%1d", st
->st_uid
, st
->st_gid
);
printf("%7D", st
->st_size
);
cp
= ctime(&st
->st_mtime
);
printf(" %-12.12s %-4.4s ", cp
+4, cp
+20);
int m1
[] = { 1, ROWN
, 'r', '-' };
int m2
[] = { 1, WOWN
, 'w', '-' };
int m3
[] = { 2, SUID
, 's', XOWN
, 'x', '-' };
int m4
[] = { 1, RGRP
, 'r', '-' };
int m5
[] = { 1, WGRP
, 'w', '-' };
int m6
[] = { 2, SGID
, 's', XGRP
, 'x', '-' };
int m7
[] = { 1, ROTH
, 'r', '-' };
int m8
[] = { 1, WOTH
, 'w', '-' };
int m9
[] = { 2, STXT
, 't', XOTH
, 'x', '-' };
int *m
[] = { m1
, m2
, m3
, m4
, m5
, m6
, m7
, m8
, m9
};
register struct stat
*st
;
for (mp
= &m
[0]; mp
< &m
[9];)
while (--n
>=0 && (st
->st_mode
&*ap
++)==0)
* Quick check for existance of directory.
if ((cp
= rindex(name
, '/')) == 0)
if (access(name
, 0) >= 0) {
* No luck, try to make all directories in path.
for (cp
= name
; *cp
; cp
++) {
if (access(name
, 0) < 0) {
if (mkdir(name
, 0777) < 0) {
chown(name
, stbuf
.st_uid
, stbuf
.st_gid
);
chmod(name
, stbuf
.st_mode
& 0777);
signal(SIGQUIT
, SIG_IGN
);
signal(SIGTERM
, SIG_IGN
);
register struct stat
*sp
;
for (cp
= dblock
.dummy
; cp
< &dblock
.dummy
[TBLOCK
]; cp
++)
sprintf(dblock
.dbuf
.mode
, "%6o ", sp
->st_mode
& 07777);
sprintf(dblock
.dbuf
.uid
, "%6o ", sp
->st_uid
);
sprintf(dblock
.dbuf
.gid
, "%6o ", sp
->st_gid
);
sprintf(dblock
.dbuf
.size
, "%11lo ", sp
->st_size
);
sprintf(dblock
.dbuf
.mtime
, "%11lo ", sp
->st_mtime
);
for (cp
= dblock
.dbuf
.chksum
;
cp
< &dblock
.dbuf
.chksum
[sizeof(dblock
.dbuf
.chksum
)]; cp
++)
for (cp
= dblock
.dummy
; cp
< &dblock
.dummy
[TBLOCK
]; cp
++)
return (response() == 'y');
while (getchar() != '\n')
checkf(name
, mode
, howmuch
)
if ((mode
& S_IFMT
) == S_IFDIR
)
return (strcmp(name
, "SCCS") != 0);
if ((l
= strlen(name
)) < 3)
if (howmuch
> 1 && name
[l
-2] == '.' && name
[l
-1] == 'o')
if (strcmp(name
, "core") == 0 ||
strcmp(name
, "errs") == 0 ||
(howmuch
> 1 && strcmp(name
, "a.out") == 0))
/* SHOULD CHECK IF IT IS EXECUTABLE */
if ((seekp
= lookup(arg
)) < 0)
fscanf(tfile
, "%s %lo", name
, &mtime
);
return (stbuf
.st_mtime
> mtime
);
a
= bsrch(s
, i
, low
, high
);
return (b
[i
+1] == ' '? 0 : -1);
if (recno
>= nblock
|| first
== 0) {
if ((i
= bread(mt
, tbuf
, TBLOCK
*nblock
)) < 0) {
fprintf(stderr
, "Tar: tape read error\n");
fprintf(stderr
, "Tar: tape blocksize error\n");
fprintf(stderr
, "Tar: blocksize = %d\n", i
);
copy(buffer
, &tbuf
[recno
++]);
if (write(mt
, tbuf
, TBLOCK
*nblock
) < 0) {
fprintf(stderr
, "Tar: tape write error\n");
copy(&tbuf
[recno
++], buffer
);
if (write(mt
, tbuf
, TBLOCK
*nblock
) < 0) {
fprintf(stderr
, "Tar: tape write error\n");
static struct mtop mtop
= {MTBSR
, 1};
mtdev
= ioctl(mt
, MTIOCGET
, &mtget
);
if (ioctl(mt
, MTIOCTOP
, &mtop
) < 0) {
fprintf(stderr
, "Tar: tape backspace error\n");
lseek(mt
, (long) -TBLOCK
*nblock
, 1);
write(mt
, tbuf
, TBLOCK
*nblock
);
register char *to
, *from
;
return (read(fd
, buf
, size
));
for (count
= 0; count
< size
; count
+= lastread
) {
lastread
= read(fd
, buf
, size
- count
);
if (getwd(buf
) == NULL
) {
fprintf(stderr
, "tar: %s\n", buf
);