-/* $OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $ */
+/* $OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $ */
/* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
-static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
-static char rcsid[] = "$OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $";
+static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/time.h>
+#include <time.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <signal.h>
#include "pax.h"
#include "extern.h"
-static void wr_archive __P((register ARCHD *, int is_app));
-static int get_arc __P((void));
-static int next_head __P((register ARCHD *));
+static void wr_archive(ARCHD *, int is_app);
+static int get_arc(void);
+static int next_head(ARCHD *);
extern sigset_t s_mask;
/*
* (no pattern matches all).
*/
-#ifdef __STDC__
void
list(void)
-#else
-void
-list()
-#endif
{
- register ARCHD *arcn;
- register int res;
+ ARCHD *arcn;
+ int res;
ARCHD archd;
time_t now;
* step through the archive until the format says it is done
*/
while (next_head(arcn) == 0) {
+ if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+ /*
+ * we need to read, to get the real filename
+ */
+ off_t cnt;
+ if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+ ? -1 : -2, &cnt))
+ (void)rd_skip(cnt + arcn->pad);
+ continue;
+ }
+
/*
* check for pattern, and user specified options match.
* When all patterns are matched we are done.
* pattern(s) (no patterns extracts all members)
*/
-#ifdef __STDC__
void
extract(void)
-#else
-void
-extract()
-#endif
{
- register ARCHD *arcn;
- register int res;
+ ARCHD *arcn;
+ int res;
off_t cnt;
ARCHD archd;
struct stat sb;
* says it is done
*/
while (next_head(arcn) == 0) {
+ if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+ /*
+ * we need to read, to get the real filename
+ */
+ if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+ ? -1 : -2, &cnt))
+ (void)rd_skip(cnt + arcn->pad);
+ continue;
+ }
/*
* check for pattern, and user specified options match. When
/*
* with -u or -D only extract when the archive member is newer
- * than the file with the same name in the file system (nos
+ * than the file with the same name in the file system (no
* test of being the same type is required).
* NOTE: this test is done BEFORE name modifications as
* specified by pax. this operation can be confusing to the
}
/*
- * Non standard -Y and -Z flag. When the exisiting file is
+ * Non standard -Y and -Z flag. When the existing file is
* same age or newer skip
*/
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
if (vflag > 1)
ls_list(arcn, now, listf);
else {
- (void)fputs(arcn->name, listf);
+ (void)safe_print(arcn->name, listf);
vfpart = 1;
}
}
(void)putc('\n', listf);
vfpart = 0;
}
- continue;
+ goto popd;
}
/*
* we have a file with data here. If we can not create it, skip
if ((fd = file_creat(arcn)) < 0) {
(void)rd_skip(arcn->skip + arcn->pad);
purg_lnk(arcn);
- continue;
+ goto popd;
}
/*
* extract the file from the archive and skip over padding and
if (!res)
(void)rd_skip(cnt + arcn->pad);
+popd:
/*
* if required, chdir around.
*/
* previously written archive.
*/
-#ifdef __STDC__
static void
-wr_archive(register ARCHD *arcn, int is_app)
-#else
-static void
-wr_archive(arcn, is_app)
- register ARCHD *arcn;
- int is_app;
-#endif
+wr_archive(ARCHD *arcn, int is_app)
{
- register int res;
- register int hlk;
- register int wr_one;
+ int res;
+ int hlk;
+ int wr_one;
off_t cnt;
- int (*wrf)();
+ int (*wrf)(ARCHD *);
int fd = -1;
time_t now;
if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
return;
+ /*
+ * if this is not append, and there are no files, we do not write a
+ * trailer
+ */
+ wr_one = is_app;
+
/*
* start up the file traversal code and format specific write
*/
- if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
+ if (ftree_start() < 0) {
+ if (is_app)
+ goto trailer;
return;
+ } else if (((*frmt->st_wr)() < 0))
+ return;
+
wrf = frmt->wr;
/*
if (iflag && (name_start() < 0))
return;
- /*
- * if this not append, and there are no files, we do no write a trailer
- */
- wr_one = is_app;
-
now = time(NULL);
/*
*/
if ((res = chk_ftime(arcn)) < 0)
break;
- if (res > 0)
+ if (res > 0) {
+ ftree_skipped_newer(arcn);
continue;
+ }
}
/*
if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
/*
* unable to obtain the crc we need, close the file,
- * purge link table entry
+ * purge link table entry
*/
rdfile_close(arcn, &fd);
purg_lnk(arcn);
if (vflag > 1)
ls_list(arcn, now, listf);
else {
- (void)fputs(arcn->name, listf);
+ (void)safe_print(arcn->name, listf);
vfpart = 1;
}
}
}
wr_one = 1;
if (res > 0) {
- /*
+ /*
* format write says no file data needs to be stored
* so we are done messing with this file
*/
break;
}
+trailer:
/*
- * tell format to write trailer; pad to block boundry; reset directory
+ * tell format to write trailer; pad to block boundary; reset directory
* mode/access times, and check if all patterns supplied by the user
* were matched. block off signals to avoid chance for multiple entry
* into the cleanup code
* is called to add the new members.
* PAX IMPLEMENTATION DETAIL NOTE:
* -u is implemented by adding the new members to the end of the archive.
- * Care is taken so that these do not end up as links to the older
+ * Care is taken so that these do not end up as links to the older
* version of the same file already stored in the archive. It is expected
* when extraction occurs these newer versions will over-write the older
* ones stored "earlier" in the archive (this may be a bad assumption as
* over write existing files that it creates.
*/
-#ifdef __STDC__
void
append(void)
-#else
-void
-append()
-#endif
{
- register ARCHD *arcn;
- register int res;
+ ARCHD *arcn;
+ int res;
ARCHD archd;
FSUB *orgfrmt;
int udev;
/*
* Do not allow an append operation if the actual archive is of a
- * different format than the user specified foramt.
+ * different format than the user specified format.
*/
if (get_arc() < 0)
return;
lnk_end();
/*
- * try to postion for write, if this fails quit. if any error occurs,
+ * try to position for write, if this fails quit. if any error occurs,
* we will refuse to write
*/
if (appnd_start(tlen) < 0)
(void)fputs("done.\n", listf);
vfpart = 0;
}
-
+
/*
* go to the writing phase to add the new members
*/
* write a new archive
*/
-#ifdef __STDC__
void
archive(void)
-#else
-void
-archive()
-#endif
{
ARCHD archd;
* (except the files are forced to be under the destination directory).
*/
-#ifdef __STDC__
void
copy(void)
-#else
-void
-copy()
-#endif
{
- register ARCHD *arcn;
- register int res;
- register int fddest;
- register char *dest_pt;
- register int dlen;
- register int drem;
+ ARCHD *arcn;
+ int res;
+ int fddest;
+ char *dest_pt;
+ int dlen;
+ int drem;
int fdsrc = -1;
struct stat sb;
ARCHD archd;
* set up the destination dir path and make sure it is a directory. We
* make sure we have a trailing / on the destination
*/
- dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1);
+ dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
+ if (dlen >= sizeof(dirbuf) ||
+ (dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
+ paxwarn(1, "directory name is too long %s", dirptr);
+ return;
+ }
dest_pt = dirbuf + dlen;
if (*(dest_pt-1) != '/') {
*dest_pt++ = '/';
+ *dest_pt = '\0';
++dlen;
}
- *dest_pt = '\0';
drem = PAXPATHLEN - dlen;
if (stat(dirptr, &sb) < 0) {
/*
* start up the hard link table; file traversal routines and the
- * modification time and access mode database
+ * modification time and access mode database
*/
if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
return;
/*
* create the destination name
*/
- if (*(arcn->name) == '/')
- res = 1;
- else
- res = 0;
- if ((arcn->nlen - res) > drem) {
+ if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
+ drem + 1) > drem) {
paxwarn(1, "Destination pathname too long %s",
arcn->name);
continue;
}
- (void)strncpy(dest_pt, arcn->name + res, drem);
- dirbuf[PAXPATHLEN] = '\0';
/*
* if existing file is same age or newer skip
res = lstat(dirbuf, &sb);
*dest_pt = '\0';
- if (res == 0) {
+ if (res == 0) {
+ ftree_skipped_newer(arcn);
if (uflag && Dflag) {
if ((arcn->sb.st_mtime<=sb.st_mtime) &&
- (arcn->sb.st_ctime<=sb.st_ctime))
+ (arcn->sb.st_ctime<=sb.st_ctime))
continue;
} else if (Dflag) {
if (arcn->sb.st_ctime <= sb.st_ctime)
}
/*
- * Non standard -Y and -Z flag. When the exisiting file is
+ * Non standard -Y and -Z flag. When the existing file is
* same age or newer skip
*/
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
}
if (vflag) {
- (void)fputs(arcn->name, listf);
+ (void)safe_print(arcn->name, listf);
vfpart = 1;
}
++flcnt;
* the specs for rd_wrbuf() for more details)
*/
-#ifdef __STDC__
-static int
-next_head(register ARCHD *arcn)
-#else
static int
-next_head(arcn)
- register ARCHD *arcn;
-#endif
+next_head(ARCHD *arcn)
{
- register int ret;
- register char *hdend;
- register int res;
- register int shftsz;
- register int hsz;
- register int in_resync = 0; /* set when we are in resync mode */
+ int ret;
+ char *hdend;
+ int res;
+ int shftsz;
+ int hsz;
+ int in_resync = 0; /* set when we are in resync mode */
int cnt = 0; /* counter for trailer function */
int first = 1; /* on 1st read, EOF isn't premature. */
res = hsz = frmt->hsz;
hdend = hdbuf;
shftsz = hsz - 1;
- for(;;) {
+ for (;;) {
/*
* keep looping until we get a contiguous FULL buffer
* (frmt->hsz is the proper size)
/*
* this format has trailers outside of valid headers
*/
- if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
+ if ((ret = (*frmt->trail)(arcn,hdbuf,in_resync,&cnt)) == 0){
/*
* valid trailer found, drain input as required
*/
* the header. NOTE: the parameters are different than trailer routines
* which encode trailers outside of the header!
*/
- if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) {
+ if (frmt->inhead && ((*frmt->trail)(arcn,NULL,0,NULL) == 0)) {
/*
* valid trailer found, drain input as required
*/
* 0 if archive found -1 otherwise
*/
-#ifdef __STDC__
static int
get_arc(void)
-#else
-static int
-get_arc()
-#endif
{
- register int i;
- register int hdsz = 0;
- register int res;
- register int minhd = BLKMULT;
+ int i;
+ int hdsz = 0;
+ int res;
+ int minhd = BLKMULT;
char *hdend;
int notice = 0;
res = BLKMULT;
hdsz = 0;
hdend = hdbuf;
- for(;;) {
+ for (;;) {
for (;;) {
/*
* fill the buffer with at least the smallest header
if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
continue;
frmt = &(fsub[ford[i]]);
- /*
+ /*
* yuck, to avoid slow special case code in the extract
* routines, just push this header back as if it was
* not seen. We have left extra space at start of the