home *** CD-ROM | disk | FTP | other *** search
- /* $Source: /u/mark/src/pax/RCS/create.c,v $
- *
- * $Revision: 1.3 $
- *
- * create.c - Create a tape archive.
- *
- * DESCRIPTION
- *
- * These functions are used to create/write and archive from an set of
- * named files.
- *
- * AUTHOR
- *
- * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- *
- * Sponsored by The USENIX Association for public distribution.
- *
- * Copyright (c) 1989 Mark H. Colburn.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in all such
- * forms and that any documentation, advertising materials, and other
- * materials related to such distribution and use acknowledge that the
- * software was developed * by Mark H. Colburn and sponsored by The
- * USENIX Association.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Log: create.c,v $
- * Revision 1.3 89/02/12 10:29:37 mark
- * Fixed misspelling of Replstr
- *
- * Revision 1.2 89/02/12 10:04:17 mark
- * 1.2 release fixes
- *
- * Revision 1.1 88/12/23 18:02:06 mark
- * Initial revision
- *
- */
-
- #ifndef lint
- static char *ident = "$Id: create.c,v 1.3 89/02/12 10:29:37 mark Exp Locker: mark $";
- static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- #endif /* ! lint */
-
-
- /* Headers */
-
- #include "pax.h"
-
-
- /* Function Prototypes */
-
- #ifdef __STDC__
-
- static void writetar(char *, Stat *);
- static void writecpio(char *, Stat *);
- #ifdef _POSIX_SOURCE /* Xn */
- static char tartype(mode_t); /* Xn */
- #else /* Xn */
- static char tartype(int);
- #endif /* Xn */
-
- #else /* !__STDC__ */
-
- static void writetar();
- static void writecpio();
- static char tartype();
-
- #endif /* __STDC__ */
-
-
- /* create_archive - create a tar archive.
- *
- * DESCRIPTION
- *
- * Create_archive is used as an entry point to both create and append
- * archives. Create archive goes through the files specified by the
- * user and writes each one to the archive if it can. Create_archive
- * knows how to write both cpio and tar headers and the padding which
- * is needed for each type of archive.
- *
- * RETURNS
- *
- * Always returns 0
- */
-
- #ifdef __STDC__
-
- int create_archive(void)
-
- #else
-
- int create_archive()
-
- #endif
- {
- char name[PATH_MAX + 1];
- Stat sb;
- int fd;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int create_archive() in create.c\n");
- #endif
- if (f_append) { /* Xn */
- if (ar_format == TAR) { /* Xn */
- (void) lseek(archivefd, -(OFFSET) (2*blocksize), SEEK_END); /* Xn */
- } else { /* Xn */
- OFFSET eoa; /* Xn */
- /* Xn */
- eoa = lseek(archivefd, (OFFSET) 0, SEEK_CUR); /* Xn */
- (void) lseek(archivefd, -(eoa - total + 87), SEEK_END); /* Xn */
- } /* Xn */
- } /* Xn */
- /* Xn */
- while (name_next(name, &sb) != -1) {
- if ((fd = openin(name, &sb)) < 0) {
- /* FIXME: pax wants to exit here??? */
- continue;
- }
-
- if (rplhead != (Replstr *)NULL) {
- rpl_name(name);
- if (strlen(name) == 0) {
- continue;
- }
- }
- if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
- /* skip file... */
- if (fd) {
- close(fd);
- }
- continue;
- }
-
- if (!f_link && sb.sb_nlink > 1) {
- #if 0 /* NIST-PCTS */
- if (islink(name, &sb)) {
- #else /* NIST-PCTS */
- if (ar_format == TAR && islink(name, &sb)) { /* NIST-PCTS */
- #endif /* NIST-PCTS */
- sb.sb_size = 0;
- }
- linkto(name, &sb);
- }
- if (ar_format == TAR) {
- writetar(name, &sb);
- } else {
- writecpio(name, &sb);
- }
- if (fd) {
- outdata(fd, name, sb.sb_size);
- }
- if (f_verbose) {
- print_entry(name, &sb);
- }
- }
-
- write_eot();
- close_archive();
- return (0);
- }
-
-
- /* writetar - write a header block for a tar file
- *
- * DESCRIPTION
- *
- * Make a header block for the file name whose stat info is in st.
- * Return header pointer for success, NULL if the name is too long.
- *
- * The tar header block is structured as follows:
- *
- * FIELD NAME OFFSET SIZE
- * -------------|---------------|------
- * name 0 100
- * mode 100 8
- * uid 108 8
- * gid 116 8
- * size 124 12
- * mtime 136 12
- * chksum 148 8
- * typeflag 156 1
- * linkname 157 100
- * magic 257 6
- * version 263 2
- * uname 265 32
- * gname 297 32
- * devmajor 329 8
- * devminor 337 8
- * prefix 345 155
- *
- * PARAMETERS
- *
- * char *name - name of file to create a header block for
- * Stat *asb - pointer to the stat structure for the named file
- *
- */
-
- #ifdef __STDC__
-
- static void writetar(char *name, Stat *asb)
-
- #else
-
- static void writetar(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- char *p;
- char *prefix = (char *)NULL;
- int i;
- int sum;
- char hdr[BLOCKSIZE];
- Link *from;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void writetar() in create.c\n");
- #endif
- memset(hdr, 0, BLOCKSIZE);
- if (strlen(name) > 256) {
- warn(name, "name too long");
- return;
- }
-
- /*
- * If the pathname is longer than TNAMLEN, but less than 256, then
- * we can split it up into the prefix and the filename.
- */
-
- if (strlen(name) > 100) {
- prefix = name;
- for (;;) {
- name = strchr(name + 1, '/');
- if (NULL == name) {
- warn(prefix, "Name too long");
- return;
- }
-
- if (strlen(name + 1) <= 100) {
- *name++ = '\0';
- break;
- }
- }
- }
-
- #ifdef S_IFLNK
- if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
- strcpy(&hdr[157], asb->sb_link);
- asb->sb_size = 0;
- }
- #endif
- strcpy(hdr, name);
- sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
- #if 0
- (void) fprintf(stderr, "create.c/writetar - asb->sb_uid: %lu; asb->sb_gid: %lu\n",
- (unsigned long) asb->sb_uid, (unsigned long) asb->sb_gid);
- (void) fflush(stderr);
- #endif /* Xn 1993-06-23 */
- sprintf(&hdr[108], "%06o \0", asb->sb_uid);
- sprintf(&hdr[116], "%06o \0", asb->sb_gid);
- sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
- sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
- strncpy(&hdr[148], " ", 8);
- hdr[156] = tartype(asb->sb_mode);
- if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
-
- if (strlen(from->l_name) > 100) {
- warn(name, "link name too long");
- return;
- }
-
- strcpy(&hdr[157], from->l_name);
- hdr[156] = LNKTYPE;
- }
- #if 0
- (void) fprintf(stderr, "create.c/writetar - name: \"%s\"; asb->sb_nlink: %lu; asb->sb_ino: %lu; asb->sb_dev: %lu; from: %p\n",
- name, (unsigned long) asb->sb_nlink, (unsigned long) asb->sb_ino, (unsigned long) asb->sb_dev, from);
- (void) fflush(stderr);
- #endif /* Xn 1993-06-21 */
-
- strcpy(&hdr[257], TMAGIC);
- strncpy(&hdr[263], TVERSION, 2);
- strcpy(&hdr[265], finduname((int) asb->sb_uid));
- strcpy(&hdr[297], findgname((int) asb->sb_gid));
- #ifndef _POSIX_SOURCE
- sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
- sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
- #endif
- if (prefix != (char *)NULL) {
- strncpy(&hdr[345], prefix, 155);
- }
-
- /* Calculate the checksum */
-
- sum = 0;
- p = hdr;
- for (i = 0; i < 500; i++) {
- sum += 0xFF & *p++;
- }
-
- /* Fill in the checksum field. */
-
- sprintf(&hdr[148], "%06o \0", sum);
-
- outwrite(hdr, BLOCKSIZE);
- }
-
-
- /* tartype - return tar file type from file mode
- *
- * DESCRIPTION
- *
- * tartype returns the character which represents the type of file
- * indicated by "mode".
- *
- * PARAMETERS
- *
- * int mode - file mode from a stat block
- *
- * RETURNS
- *
- * The character which represents the particular file type in the
- * ustar standard headers.
- */
-
- #ifdef __STDC__
-
- #ifdef _POSIX_SOURCE /* Xn */
- static char tartype(mode_t mode) /* Xn */
- #else /* Xn */
- static char tartype(int mode)
- #endif /* Xn */
-
- #else
-
- static char tartype(mode)
- int mode;
-
- #endif
- {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static char tartype() in create.c\n");
- #endif
- switch (mode & S_IFMT) {
-
- #ifdef S_IFCTG
- case S_IFCTG:
- return(CONTTYPE);
- #endif
-
- case S_IFDIR:
- return (DIRTYPE);
-
- #ifdef S_IFLNK
- case S_IFLNK:
- return (SYMTYPE);
- #endif
-
- #ifdef S_IFIFO /* Xn */
- case S_IFIFO:
- return (FIFOTYPE);
- #endif
-
- #ifdef S_IFCHR
- case S_IFCHR:
- return (CHRTYPE);
- #endif
-
- #ifdef S_IFBLK
- case S_IFBLK:
- return (BLKTYPE);
- #endif
- /* Xn */
- #ifdef S_IFSOCK /* Xn */
- case S_IFSOCK: /* Xn */
- return (SOCKTYPE); /* Xn */
- #endif /* Xn */
-
- default:
- return (REGTYPE);
- }
- }
-
-
- /* writecpio - write a cpio archive header
- *
- * DESCRIPTION
- *
- * Writes a new CPIO style archive header for the file specified.
- *
- * PARAMETERS
- *
- * char *name - name of file to create a header block for
- * Stat *asb - pointer to the stat structure for the named file
- */
-
- #ifdef __STDC__
-
- static void writecpio(char *name, Stat *asb)
-
- #else
-
- static void writecpio(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- uint namelen;
- char header[M_STRLEN + H_STRLEN + 1];
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void writecpio() in create.c\n");
- #endif
- namelen = (uint) strlen(name) + 1;
- strcpy(header, M_ASCII);
-
- sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
- USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode),
- USH(asb->sb_uid), USH(asb->sb_gid));
- sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
- USH(asb->sb_nlink),
- #ifndef _POSIX_SOURCE
- USH(asb->sb_rdev),
- #else
- USH(0),
- #endif
- f_mtime ? asb->sb_mtime : time((time_t *) 0),
- namelen, asb->sb_size);
- outwrite(header, M_STRLEN + H_STRLEN);
- outwrite(name, namelen);
- #ifdef S_IFLNK
- if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
- outwrite(asb->sb_link, (uint) asb->sb_size);
- }
- #endif /* S_IFLNK */
- }
-