📄 tar.c
字号:
/* Should there be a timestamp if the chown failes? -- KS */ timestamp(file);}void timestamp(file)char *file;{ struct utimbuf buf; buf.modtime = buf.actime = convert(header.dbuf.mtime, LONG_TYPE); utime(file, &buf);}void copy(file, from, to, bytes)char *file;int from, to;register long bytes;{ register int rest; int blocks = (int) ((bytes + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE); if (verbose_flag) string_print(NIL_PTR, "%s, %d tape blocks\n", file, blocks); while (blocks--) { (void) bread(from, io_buffer, TBLOCK_SIZE); rest = (bytes > (long) TBLOCK_SIZE) ? TBLOCK_SIZE : (int) bytes; mwrite(to, io_buffer, (to == tar_fd) ? TBLOCK_SIZE : rest); bytes -= (long) rest; }}long convert(str, type)char str[];int type;{ register long ac = 0L; register int i; for (i = 0; i < type; i++) { if (str[i] >= '0' && str[i] <= '7') { ac <<= 3; ac += (long) (str[i] - '0'); } } return ac;}int checksum(){ register char *ptr = header.member.m_checksum; register int ac = 0; while (ptr < &header.member.m_checksum[INT_TYPE]) *ptr++ = ' '; ptr = header.hdr_block; while (ptr < &header.hdr_block[TBLOCK_SIZE]) ac += *ptr++; return ac;}int is_dir(file)register char *file;{ while (*file++ != '\0'); return(*(file - 2) == '/');}char *path_name(file)register char *file;{ string_print(pathname, "%s%s", path, file); return pathname;}void add_path(name)register char *name;{ register char *path_ptr = path; while (*path_ptr) path_ptr++; if (name == NIL_PTR) { while (*path_ptr-- != '/'); while (*path_ptr != '/' && path_ptr != path) path_ptr--; if (*path_ptr == '/') path_ptr++; *path_ptr = '\0'; } else { while (*name) { if (path_ptr == &path[NAME_SIZE]) error("Pathname too long", NIL_PTR); *path_ptr++ = *name++; } *path_ptr++ = '/'; *path_ptr = '\0'; }}/* * add a file to the archive*/void add_file(file)register char *file;{ struct stat st; char *linkname; register int fd = -1; char namebuf[16]; /* -Dal */ char cwd[129]; /* -KS */#ifdef HAVE_SYMLINK if (lstat(file, &st) < 0) {#else if (stat(file, &st) < 0) {#endif string_print(NIL_PTR, "%s: %s\n", file, strerror(errno)); return; } if (st.st_dev == ar_dev && st.st_ino == ar_inode) { string_print(NIL_PTR, "Cannot tar current archive file (%s)\n", file); return; } /* marks@mgse Mon Sep 25 12:06:28 CDT 1989 */ if ((fd = add_open(file, &st)) < 0) { string_print(NIL_PTR, "Cannot open %s\n", file); return; } make_header(path_name(file), &st); if ((linkname = is_linked(&st)) != NULL) { strncpy(header.dbuf.linkname, linkname, (size_t) NAMSIZ); header.dbuf.typeflag = '1'; if (verbose_flag) string_print(NIL_PTR, "linked %s to %s\n", header.dbuf.linkname, file); string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); } else { is_added(&st, file); switch (st.st_mode & S_IFMT) { case S_IFREG: header.dbuf.typeflag = '0'; string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); copy(path_name(file), fd, tar_fd, (long) st.st_size); break; case S_IFDIR: header.dbuf.typeflag = '5'; string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); verb_print("read directory", file); if (norec_flag) break; if (NULL == getcwd(cwd, (int) sizeof cwd)) string_print(NIL_PTR, "Error: cannot getcwd()\n"); else if (chdir(file) < 0) string_print(NIL_PTR, "Cannot chdir to %s: %s\n", file, strerror(errno)); else { add_path(file);#ifdef DIRECT_3 { DIR *dirp; struct direct *dp; struct stat dst; add_close(fd); fd= 0; dirp = opendir("."); while (NULL != (dp = readdir(dirp))) if (strcmp(dp->d_name, ".") == 0) is_linked(&st); else if (strcmp(dp->d_name, "..") == 0) { if (stat("..", &dst) == 0) is_linked(&dst); } else { strcpy(namebuf, dp->d_name); add_file(namebuf); } closedir(dirp); }#else { int i; struct direct dir; struct stat dst; for (i = 0; i < 2; i++) { /* . and .. */ mread(fd, &dir, sizeof(dir)); if (strcmp(dir.d_name, ".") == 0) is_linked(&st); else if (strcmp(dir.d_name, "..") == 0) { if (stat("..", &dst) == 0) is_linked(&dst); } else break; } while (bread(fd, &dir, sizeof(dir)) == sizeof(dir)) if (dir.d_ino) { strncpy(namebuf, dir.d_name, (size_t) DIRSIZ); namebuf[DIRSIZ] = '\0'; add_file(namebuf); } }#endif chdir(cwd); add_path(NIL_PTR); *file = 0; } break;#ifdef HAVE_SYMLINK case S_IFLNK: { int i; header.dbuf.typeflag = '2'; verb_print("read symlink", file); i = readlink(file, header.dbuf.linkname, sizeof(header.dbuf.linkname) - 1); if (i < 0) { string_print(NIL_PTR, "Cannot read symbolic link %s: %s\n", file, strerror(errno)); return; } header.dbuf.linkname[i] = 0; string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); break; }#endif#ifdef HAVE_FIFO case S_IFIFO: header.dbuf.typeflag = '6'; verb_print("read fifo", file); string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); break;#endif case S_IFBLK: header.dbuf.typeflag = '4'; if (verbose_flag) { char sizebuf[TSIZLEN + 1]; strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN); sizebuf[TSIZLEN] = 0; string_print(NIL_PTR, "read block device %s major %s minor %s\n", file, header.dbuf.devmajor, header.dbuf.devminor, sizebuf); } string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); break; case S_IFCHR: header.dbuf.typeflag = '3'; if (verbose_flag) string_print(NIL_PTR, "read character device %s major %s minor %s\n", file, header.dbuf.devmajor, header.dbuf.devminor); string_print(header.member.m_checksum, "%I ", checksum()); mwrite(tar_fd, (char *) &header, sizeof(header)); break; default: is_deleted(&st); string_print(NIL_PTR, "Tar: %s unknown file type. Not added.\n", file); *file = 0; } } flush(); add_close(fd);}void verb_print(s1, s2)char *s1, *s2;{ if (verbose_flag) string_print(NIL_PTR, "%s: %s\n", s1, s2);}void add_close(fd)int fd;{ if (fd != 0) close(fd);}/* * open file 'file' to be added to archive, return file descriptor*/int add_open(file, st)char *file;struct stat *st;{ int fd; if (((st->st_mode & S_IFMT) != S_IFREG) && ((st->st_mode & S_IFMT) != S_IFDIR)) return 0; fd = open(file, O_RDONLY); if (fd == -1) fprintf(stderr, "open failed: %s\n", strerror(errno)); return fd;}void make_header(file, st)char *file;register struct stat *st;{ register char *ptr = header.member.m_name; struct passwd *pwd; struct group *grp; clear_header(); while (*ptr++ = *file++); if ((st->st_mode & S_IFMT) == S_IFDIR) { /* fixed test -Dal */ *(ptr - 1) = '/'; } string_print(header.member.m_mode, "%I ", st->st_mode & 07777); string_print(header.member.m_uid, "%I ", st->st_uid); string_print(header.member.m_gid, "%I ", st->st_gid); if ((st->st_mode & S_IFMT) == S_IFREG) string_print(header.member.m_size, "%L ", st->st_size); else strncpy(header.dbuf.size, "0", (size_t) TSIZLEN); string_print(header.member.m_time, "%L ", st->st_mtime); strncpy(header.dbuf.magic, TMAGIC, (size_t) TMAGLEN); header.dbuf.version[0] = 0; header.dbuf.version[1] = 0; pwd = getpwuid(st->st_uid); strncpy(header.dbuf.uname, (pwd != NULL ? pwd->pw_name : "nobody"), TUNMLEN); grp = getgrgid(st->st_gid); strncpy(header.dbuf.gname, (grp != NULL ? grp->gr_name : "nobody"), TGNMLEN); if (st->st_mode & (S_IFBLK | S_IFCHR)) { string_print(header.dbuf.devmajor, "%I ", (st->st_rdev >> 8)); string_print(header.dbuf.devminor, "%I ", (st->st_rdev & 0xFF)); } header.dbuf.prefix[0] = 0;}void is_added(st, file)struct stat *st;char *file;{ struct link *new; char *name; if ((*file == 0) || (st->st_nlink == 1)) return; name = path_name(file); new = (struct link *) malloc(sizeof(struct link) + strlen(name)); if (new == NULL) { print("Out of memory\n"); return; } new->next = link_top; new->dev = st->st_dev; new->ino = st->st_ino; new->nlink = st->st_nlink - 1; strcpy(new->name, name); link_top = new;}void is_deleted(st)struct stat *st;{ struct link *old; if ((old = link_top) != NULL) { link_top = old->next; free(old); }}char *is_linked(st)struct stat *st;{ struct link *cur = link_top; struct link **pre = &link_top; static char name[NAMSIZ]; while (cur != NULL) if ((cur->dev != st->st_dev) || (cur->ino != st->st_ino)) { pre = &cur->next; cur = cur->next; } else { if (--cur->nlink == 0) { *pre = cur->next; strncpy(name, cur->name, NAMSIZ); return name; } return cur->name; } return NULL;}void clear_header(){ register char *ptr = header.hdr_block; while (ptr < &header.hdr_block[TBLOCK_SIZE]) *ptr++ = '\0';}void adjust_boundary(){ clear_header(); mwrite(tar_fd, (char *) &header, sizeof(header));#ifndef POSIX_COMP while (total_blocks++ < BLOCK_BOUNDARY) mwrite(tar_fd, (char *) &header, sizeof(header));#else mwrite(tar_fd, (char *) &header, sizeof(header));#endif (void) close(tar_fd);}void mread(fd, address, bytes)int fd, bytes;char *address;{ if (bread(fd, address, bytes) != bytes) error("Tar: read error.", NIL_PTR);}void mwrite(fd, address, bytes)int fd, bytes;char *address;{ if (bwrite(fd, address, bytes) != bytes) error("Tar: write error.", NIL_PTR); total_blocks++;}int bread(fd, address, bytes)int fd, bytes;char *address;{ int n = 0, r; while (n < bytes) { if ((r = read(fd, address + n, bytes - n)) <= 0) { if (r < 0) return r; break; } n += r; } return n;}int bwrite(fd, address, bytes)int fd, bytes;char *address;{ int n = 0, r; while (n < bytes) { if ((r = write(fd, address + n, bytes - n)) <= 0) { if (r < 0) return r; break; } n += r; } return n;}char output[TBLOCK_SIZE];void print(str) /* changed to use stderr rather than stdout * -Dal */register char *str;{ static int indx = 0; if (str == NIL_PTR) { write(2, output, indx); indx = 0; return; } while (*str) { output[indx++] = *str++; if (indx == TBLOCK_SIZE) { write(2, output, TBLOCK_SIZE); indx = 0; } }}char *num_out(number)register long number;{ static char num_buf[12]; register int i; for (i = 11; i--;) { num_buf[i] = (number & 07) + '0'; number >>= 3; } return num_buf;}/*VARARGS2*/#if __STDC__void string_print(char *buffer, char *fmt,...)#elsevoid string_print(buffer, fmt)char *buffer;char *fmt;#endif{ va_list args; register char *buf_ptr; char *scan_ptr; char buf[STRING_SIZE]; BOOL pr_fl, i; if (pr_fl = (buffer == NIL_PTR)) buffer = buf; va_start(args, fmt); buf_ptr = buffer; while (*fmt) { if (*fmt == '%') { fmt++; switch (*fmt++) { case 's': scan_ptr = (char *) (va_arg(args, char *)); break; case 'I': scan_ptr = num_out((long) (va_arg(args, int))); for (i = 0; i < 5; i++) scan_ptr++; break; case 'L': scan_ptr = num_out((long) va_arg(args, long)); break; case 'd': scan_ptr = num_out((long) va_arg(args, int)); while (*scan_ptr == '0') scan_ptr++; scan_ptr--; break; default: scan_ptr = ""; } while (*buf_ptr++ = *scan_ptr++); buf_ptr--; } else *buf_ptr++ = *fmt++; } *buf_ptr = '\0'; if (pr_fl) print(buffer); va_end(args);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -