static void tape_clear_rest_of_block (int handle) { while (output_buffer_remaining_size < io_block_size) { if ((io_block_size - output_buffer_remaining_size) > BLOCKSIZE) tape_buffered_write (zero_block, handle, BLOCKSIZE); else tape_buffered_write (zero_block, handle, io_block_size - output_buffer_remaining_size); } }
void tape_pad_output (int handle, int offset) { int pad; switch (archive_format) { case HPUX_OLD_ASCII_FORMAT: case OLD_ASCII_FORMAT: pad = 0; break; default: pad = PADDING (offset, 2); break; case CRC_ASCII_FORMAT: case NEW_ASCII_FORMAT: pad = PADDING (offset, 4); break; case GNUTAR_FORMAT: case POSIX_FORMAT: case V7_FORMAT: pad = PADDING (offset, BLOCKSIZE); break; } if (pad != 0) tape_buffered_write (zero_block, handle, pad); }
void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des) { int name_len; union tar_record tar_rec; struct tar_header *tar_hdr = (struct tar_header *) &tar_rec; memset (&tar_rec, 0, sizeof tar_rec); /* process_copy_out must ensure that file_hdr->c_name is short enough, or we will lose here. */ name_len = strlen (file_hdr->c_name); if (name_len <= TARNAMESIZE) { strncpy (tar_hdr->name, file_hdr->c_name, name_len); } else { /* Fit as much as we can into `name', the rest into `prefix'. */ int prefix_len = split_long_name (file_hdr->c_name, name_len); strncpy (tar_hdr->prefix, file_hdr->c_name, prefix_len); strncpy (tar_hdr->name, file_hdr->c_name + prefix_len + 1, name_len - prefix_len - 1); } /* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal digits */ to_oct (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode); to_oct (file_hdr->c_uid, 8, tar_hdr->uid); to_oct (file_hdr->c_gid, 8, tar_hdr->gid); to_oct (file_hdr->c_filesize, 12, tar_hdr->size); to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime); switch (file_hdr->c_mode & CP_IFMT) { case CP_IFREG: if (file_hdr->c_tar_linkname) { /* process_copy_out makes sure that c_tar_linkname is shorter than TARLINKNAMESIZE. */ strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname, TARLINKNAMESIZE); tar_hdr->typeflag = LNKTYPE; to_oct (0, 12, tar_hdr->size); } else tar_hdr->typeflag = REGTYPE; break; case CP_IFDIR: tar_hdr->typeflag = DIRTYPE; break; case CP_IFCHR: tar_hdr->typeflag = CHRTYPE; break; case CP_IFBLK: tar_hdr->typeflag = BLKTYPE; break; #ifdef CP_IFIFO case CP_IFIFO: tar_hdr->typeflag = FIFOTYPE; break; #endif /* CP_IFIFO */ #ifdef CP_IFLNK case CP_IFLNK: tar_hdr->typeflag = SYMTYPE; /* process_copy_out makes sure that c_tar_linkname is shorter than TARLINKNAMESIZE. */ strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname, TARLINKNAMESIZE); to_oct (0, 12, tar_hdr->size); break; #endif /* CP_IFLNK */ } if (archive_format == arf_ustar) { char *name; strncpy (tar_hdr->magic, TMAGIC, TMAGLEN); strncpy (tar_hdr->version, TVERSION, TVERSLEN); name = getuser (file_hdr->c_uid); if (name) strcpy (tar_hdr->uname, name); name = getgroup (file_hdr->c_gid); if (name) strcpy (tar_hdr->gname, name); to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor); to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor); } to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum); tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE); }
static void copy_out_one_file (int handle, dynamic_string *input_name, struct stat *stat_info) { struct new_cpio_header header; int input_handle; /* source file descriptor */ char *p; /* Set values in output header. */ header.c_magic = 070707; header.c_dev_maj = major (stat_info->st_dev); header.c_dev_min = minor (stat_info->st_dev); header.c_ino = stat_info->st_ino; #if DOSWIN /* DJGPP doesn't support st_rdev. Repair that. */ stat_info->st_rdev = stat_info->st_dev; #endif /* For POSIX systems that don't define the S_IF macros, we can't assume that S_ISfoo means the standard Unix S_IFfoo bit(s) are set. So do it manually, with a different name. Bleah. */ header.c_mode = (stat_info->st_mode & 07777); if (S_ISREG (stat_info->st_mode)) header.c_mode |= CP_IFREG; else if (S_ISDIR (stat_info->st_mode)) header.c_mode |= CP_IFDIR; #ifdef S_ISBLK else if (S_ISBLK (stat_info->st_mode)) header.c_mode |= CP_IFBLK; #endif #ifdef S_ISCHR else if (S_ISCHR (stat_info->st_mode)) header.c_mode |= CP_IFCHR; #endif #ifdef S_ISFIFO else if (S_ISFIFO (stat_info->st_mode)) header.c_mode |= CP_IFIFO; #endif #ifdef S_ISLNK else if (S_ISLNK (stat_info->st_mode)) header.c_mode |= CP_IFLNK; #endif #ifdef S_ISSOCK else if (S_ISSOCK (stat_info->st_mode)) header.c_mode |= CP_IFSOCK; #endif #ifdef S_ISNWK else if (S_ISNWK (stat_info->st_mode)) header.c_mode |= CP_IFNWK; #endif header.c_uid = stat_info->st_uid; header.c_gid = stat_info->st_gid; header.c_nlink = stat_info->st_nlink; header.c_rdev_maj = major (stat_info->st_rdev); header.c_rdev_min = minor (stat_info->st_rdev); header.c_mtime = (stat_info->st_mtime < 0) ? 0 :stat_info->st_mtime; header.c_filesize = stat_info->st_size; header.c_chksum = 0; header.c_tar_linkname = NULL; /* Handle HPUX CDF files. */ possibly_munge_cdf_directory_name (input_name->string, &header); if ((*name_too_long) (header.c_name)) { error (0, 0, _("%s: file name too long"), header.c_name); return; } /* FIXME: there is a memory leak here, between this and the HPUX stuff above. */ header.c_name = possibly_rename_file (header.c_name); /* Copy the named file to the output. */ switch (header.c_mode & CP_IFMT) { case CP_IFREG: #ifndef __MSDOS__ if (archive_format == V7_FORMAT || archive_format == POSIX_FORMAT || archive_format == GNUTAR_FORMAT) { char *otherfile; if ((otherfile = find_inode_file (header.c_ino, header.c_dev_maj, header.c_dev_min))) { header.c_tar_linkname = otherfile; (*header_writer) (&header, handle); break; } } if ((archive_format == NEW_ASCII_FORMAT || archive_format == CRC_ASCII_FORMAT) && header.c_nlink > 1) if (last_link (&header) ) writeout_other_defers (&header, handle); else { add_link_defer (&header); break; } #endif input_handle = open (input_name->string, O_RDONLY | O_BINARY, 0); if (input_handle < 0) { error (0, errno, "%s", input_name->string); return; } if (archive_format == CRC_ASCII_FORMAT) header.c_chksum = read_for_checksum (input_handle, header.c_filesize, input_name->string); (*header_writer) (&header, handle); copy_files_disk_to_tape (input_handle, handle, header.c_filesize, input_name->string); #ifndef __MSDOS__ if (archive_format == V7_FORMAT || archive_format == POSIX_FORMAT || archive_format == GNUTAR_FORMAT) add_inode (header.c_ino, header.c_name, header.c_dev_maj, header.c_dev_min); #endif tape_pad_output (handle, header.c_filesize); if (close (input_handle) < 0) error (0, errno, "%s", input_name->string); if (reset_access_time_option) { struct utimbuf times; /* Initialize this in case it has members we don't know to set. */ memset (×, 0, sizeof (struct utimbuf)); times.actime = stat_info->st_atime; times.modtime = stat_info->st_mtime; /* Silently ignore EROFS because reading the file won't have upset its timestamp if it's on a read-only filesystem. */ if (utime (header.c_name, ×) < 0 && errno != EROFS) error (0, errno, _("%s: error resetting file access time"), header.c_name); } break; case CP_IFDIR: header.c_filesize = 0; (*header_writer) (&header, handle); break; #ifndef __MSDOS__ case CP_IFCHR: case CP_IFBLK: #ifdef CP_IFSOCK case CP_IFSOCK: #endif #ifdef CP_IFIFO case CP_IFIFO: #endif if (archive_format == V7_FORMAT) { error (0, 0, _("%s not dumped: not a regular file"), header.c_name); return; } else if (archive_format == POSIX_FORMAT || archive_format == GNUTAR_FORMAT) { char *otherfile = find_inode_file (header.c_ino, header.c_dev_maj, header.c_dev_min); if (otherfile) { /* This file is linked to another file already in the archive, so write it out as a hard link. */ header.c_mode = (stat_info->st_mode & 07777); header.c_mode |= CP_IFREG; header.c_tar_linkname = otherfile; (*header_writer) (&header, handle); break; } add_inode (header.c_ino, header.c_name, header.c_dev_maj, header.c_dev_min); } header.c_filesize = 0; (*header_writer) (&header, handle); break; #endif #ifdef CP_IFLNK case CP_IFLNK: { char *link_name = (char *) xmalloc (stat_info->st_size + 1); int link_size = readlink (input_name->string, link_name, stat_info->st_size); if (link_size < 0) { error (0, errno, "%s", input_name->string); free (link_name); return; } header.c_filesize = link_size; if (archive_format == V7_FORMAT || archive_format == POSIX_FORMAT || archive_format == GNUTAR_FORMAT) { /* FIXME: tar can do long symlinks. */ if (link_size + 1 > 100) error (0, 0, _("%s: symbolic link too long"), header.c_name); else { link_name[link_size] = '\0'; header.c_tar_linkname = link_name; (*header_writer) (&header, handle); } } else { (*header_writer) (&header, handle); tape_buffered_write (link_name, handle, link_size); tape_pad_output (handle, link_size); } free (link_name); } break; #endif default: error (0, 0, _("%s: unknown file type"), input_name->string); } /* FIXME shouldn't do this for each file. Should maintain a dstring somewhere. */ free (header.c_name); header.c_name = NULL; }