-/* $OpenBSD: ar_io.c,v 1.45 2014/05/21 04:17:56 guenther Exp $ */
+/* $OpenBSD: ar_io.c,v 1.46 2014/05/23 19:47:49 guenther Exp $ */
/* $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $ */
/*-
}
/*
- * ar_close()
+ * ar_close(int int_sig)
* closes archive device, increments volume number, and prints i/o summary
+ * If in_sig is set we're in a signal handler and can't flush stdio.
*/
void
-ar_close(void)
+ar_close(int in_sig)
{
int status;
did_io = io_ok = flcnt = 0;
return;
}
+ if (!in_sig)
+ fflush(listf);
/*
* Close archive file. This may take a LONG while on tapes (we may be
* broken).
*/
if (vflag && (artyp == ISTAPE)) {
- if (vfpart)
- (void)putc('\n', listf);
- (void)fprintf(listf,
- "%s: Waiting for tape drive close to complete...",
- argv0);
- (void)fflush(listf);
+ (void)dprintf(listfd,
+ "%s%s: Waiting for tape drive close to complete...",
+ vfpart ? "\n" : "", argv0);
}
/*
if (vflag && (artyp == ISTAPE)) {
- (void)fputs("done.\n", listf);
+ (void)write(listfd, "done.\n", sizeof("done.\n")-1);
vfpart = 0;
- (void)fflush(listf);
}
arfd = -1;
* Print out a summary of I/O for this archive volume.
*/
if (vfpart) {
- (void)putc('\n', listf);
+ (void)write(listfd, "\n", 1);
vfpart = 0;
}
* could have written anything yet.
*/
if (frmt == NULL) {
- (void)fprintf(listf, "%s: unknown format, %llu bytes skipped.\n",
- argv0, rdcnt);
- (void)fflush(listf);
+ (void)dprintf(listfd,
+ "%s: unknown format, %llu bytes skipped.\n", argv0, rdcnt);
flcnt = 0;
return;
}
if (strcmp(NM_TAR, argv0) != 0)
- (void)fprintf(listf,
- "%s: %s vol %d, %lu files, %llu bytes read, %llu bytes written.\n",
+ (void)dprintf(listfd, "%s: %s vol %d, %lu files,"
+ " %llu bytes read, %llu bytes written.\n",
argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
#ifndef NOCPIO
else if (strcmp(NM_CPIO, argv0) == 0)
- (void)fprintf(listf, "%llu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
+ (void)dprintf(listfd, "%llu blocks\n",
+ (rdcnt ? rdcnt : wrcnt) / 5120);
#endif /* !NOCPIO */
- (void)fflush(listf);
flcnt = 0;
}
*/
if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0)
syswarn(0, errno, "Unable to set signal mask");
- ar_close();
+ ar_close(0);
if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0)
syswarn(0, errno, "Unable to restore signal mask");
-/* $OpenBSD: ar_subs.c,v 1.38 2014/02/05 20:35:42 halex Exp $ */
+/* $OpenBSD: ar_subs.c,v 1.39 2014/05/23 19:47:49 guenther Exp $ */
/* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */
/*-
*/
(void)(*frmt->end_rd)();
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
- ar_close();
+ ar_close(0);
pat_chk();
}
*/
(void)(*frmt->end_rd)();
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
- ar_close();
- proc_dir();
+ ar_close(0);
+ proc_dir(0);
pat_chk();
}
wr_fin();
}
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
- ar_close();
+ ar_close(0);
if (tflag)
- proc_dir();
+ proc_dir(0);
ftree_chk();
}
* multiple entry into the cleanup code.
*/
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
- ar_close();
- proc_dir();
+ ar_close(0);
+ proc_dir(0);
ftree_chk();
}
-/* $OpenBSD: extern.h,v 1.40 2014/01/19 10:22:57 guenther Exp $ */
+/* $OpenBSD: extern.h,v 1.41 2014/05/23 19:47:49 guenther Exp $ */
/* $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $ */
/*-
extern const char *gzip_program;
extern int force_one_volume;
int ar_open(const char *);
-void ar_close(void);
+void ar_close(int _in_sig);
void ar_drain(void);
int ar_set_wr(void);
int ar_app_ok(void);
extern char *dirptr;
extern char *argv0;
extern FILE *listf;
+extern int listfd;
extern char *tempfile;
extern char *tempbase;
extern int havechd;
int get_atdir(dev_t, ino_t, time_t *, time_t *);
int dir_start(void);
void add_dir(char *, struct stat *, int);
-void proc_dir(void);
+void proc_dir(int _in_sig);
u_int st_hash(char *, int, int);
/*
-/* $OpenBSD: pax.c,v 1.35 2014/01/09 03:12:25 guenther Exp $ */
+/* $OpenBSD: pax.c,v 1.36 2014/05/23 19:47:49 guenther Exp $ */
/* $NetBSD: pax.c,v 1.5 1996/03/26 23:54:20 mrg Exp $ */
/*-
char *argv0; /* root of argv[0] */
sigset_t s_mask; /* signal mask for cleanup critical sect */
FILE *listf = stderr; /* file pointer to print file list to */
+int listfd = STDERR_FILENO; /* fd matching listf, for sighandler output */
char *tempfile; /* tempfile to use for mkstemp(3) */
char *tempbase; /* basename of tempfile to use for mkstemp(3) */
/*
* restore modes and times for any dirs we may have created
- * or any dirs we may have read. Set vflag and vfpart so the user
- * will clearly see the message on a line by itself.
+ * or any dirs we may have read.
*/
- vflag = vfpart = 1;
/* paxwarn() uses stdio; fake it as well as we can */
if (which_sig == SIGXCPU)
- strlcpy(errbuf, "CPU time limit reached, cleaning up.\n",
+ strlcpy(errbuf, "\nCPU time limit reached, cleaning up.\n",
sizeof errbuf);
else
- strlcpy(errbuf, "Signal caught, cleaning up.\n",
+ strlcpy(errbuf, "\nSignal caught, cleaning up.\n",
sizeof errbuf);
(void) write(STDERR_FILENO, errbuf, strlen(errbuf));
- ar_close(); /* XXX signal race */
- proc_dir(); /* XXX signal race */
+ ar_close(1);
+ proc_dir(1);
if (tflag)
- atdir_end(); /* XXX signal race */
+ atdir_end();
_exit(1);
}
paxwarn(1, "Unable to set up signal mask");
return(-1);
}
+
+ /* snag the fd to be used from the signal handler */
+ listfd = fileno(listf);
+
memset(&n_hand, 0, sizeof n_hand);
n_hand.sa_mask = s_mask;
n_hand.sa_flags = 0;
-/* $OpenBSD: tables.c,v 1.31 2014/05/07 14:56:57 tedu Exp $ */
+/* $OpenBSD: tables.c,v 1.32 2014/05/23 19:47:49 guenther Exp $ */
/* $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $ */
/*-
add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
{
ATDIR *pt;
+ sigset_t allsigs, savedsigs;
u_int indx;
if (atab == NULL)
/*
* add it to the front of the hash chain
*/
- if ((pt = (ATDIR *)malloc(sizeof(ATDIR))) != NULL) {
+ sigfillset(&allsigs);
+ sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
+ if ((pt = malloc(sizeof *pt)) != NULL) {
if ((pt->name = strdup(fname)) != NULL) {
pt->dev = dev;
pt->ino = ino;
pt->atime = atime;
pt->fow = atab[indx];
atab[indx] = pt;
+ sigprocmask(SIG_SETMASK, &savedsigs, NULL);
return;
}
(void)free((char *)pt);
}
+ sigprocmask(SIG_SETMASK, &savedsigs, NULL);
paxwarn(1, "Directory access time reset table ran out of memory");
return;
}
{
ATDIR *pt;
ATDIR **ppt;
+ sigset_t allsigs, savedsigs;
u_int indx;
if (atab == NULL)
/*
* found it. return the times and remove the entry from the table.
*/
+ sigfillset(&allsigs);
+ sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
*ppt = pt->fow;
+ sigprocmask(SIG_SETMASK, &savedsigs, NULL);
*mtime = pt->mtime;
*atime = pt->atime;
(void)free((char *)pt->name);
add_dir(char *name, struct stat *psb, int frc_mode)
{
DIRDATA *dblk;
+ sigset_t allsigs, savedsigs;
char realname[MAXPATHLEN], *rp;
if (dirp == NULL)
" directory: %s", name);
return;
}
+ sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
dirp = dblk;
dirsize *= 2;
+ sigprocmask(SIG_SETMASK, &savedsigs, NULL);
}
dblk = &dirp[dircnt];
if ((dblk->name = strdup(name)) == NULL) {
dblk->mtime = psb->st_mtime;
dblk->atime = psb->st_atime;
dblk->frc_mode = frc_mode;
+ sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
++dircnt;
+ sigprocmask(SIG_SETMASK, &savedsigs, NULL);
}
/*
- * proc_dir()
+ * proc_dir(int in_sig)
* process all file modes and times stored for directories CREATED
- * by pax
+ * by pax. If in_sig is set, we're in a signal handler and can't
+ * free stuff.
*/
void
-proc_dir(void)
+proc_dir(int in_sig)
{
DIRDATA *dblk;
size_t cnt;
set_pmode(dblk->name, dblk->mode);
if (patime || pmtime)
set_ftime(dblk->name, dblk->mtime, dblk->atime, 0);
- free(dblk->name);
+ if (!in_sig)
+ free(dblk->name);
}
- free(dirp);
+ if (!in_sig)
+ free(dirp);
dirp = NULL;
dircnt = 0;
}