📄 system.c
字号:
if (errno != EINTR) { waitpid_error (use_compress_program_option); break; } if (WIFSIGNALED (wait_status)) { kill (child_pid, WTERMSIG (wait_status)); exit_status = TAREXIT_FAILURE; } else if (WEXITSTATUS (wait_status) != 0) exit_status = WEXITSTATUS (wait_status); exit (exit_status);}/* Set ARCHIVE for uncompressing, then reading an archive. */pid_tsys_child_open_for_uncompress (void){ int parent_pipe[2]; int child_pipe[2]; pid_t grandchild_pid; pid_t child_pid; int wait_status; xpipe (parent_pipe); child_pid = xfork (); if (child_pid > 0) { /* The parent tar is still here! Just clean up. */ archive = parent_pipe[PREAD]; xclose (parent_pipe[PWRITE]); return child_pid; } /* The newborn child tar is here! */ program_name = _("tar (child)"); xdup2 (parent_pipe[PWRITE], STDOUT_FILENO); xclose (parent_pipe[PREAD]); /* Check if we need a grandchild tar. This happens only if either: a) we're reading stdin: to force unblocking; b) the file is to be accessed by rmt: compressor doesn't know how; c) the file is not a plain file. */ if (strcmp (archive_name_array[0], "-") != 0 && !_remdev (archive_name_array[0]) && is_regular_file (archive_name_array[0])) { /* We don't need a grandchild tar. Open the archive and lauch the uncompressor. */ archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW); if (archive < 0) open_fatal (archive_name_array[0]); xdup2 (archive, STDIN_FILENO); execlp (use_compress_program_option, use_compress_program_option, "-d", (char *) 0); exec_fatal (use_compress_program_option); } /* We do need a grandchild tar. */ xpipe (child_pipe); grandchild_pid = xfork (); if (grandchild_pid == 0) { /* The newborn grandchild tar is here! Launch the uncompressor. */ program_name = _("tar (grandchild)"); xdup2 (child_pipe[PREAD], STDIN_FILENO); xclose (child_pipe[PWRITE]); execlp (use_compress_program_option, use_compress_program_option, "-d", (char *) 0); exec_fatal (use_compress_program_option); } /* The child tar is still here! */ /* Prepare for unblocking the data from the archive into the uncompressor. */ xdup2 (child_pipe[PWRITE], STDOUT_FILENO); xclose (child_pipe[PREAD]); if (strcmp (archive_name_array[0], "-") == 0) archive = STDIN_FILENO; else archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW, rsh_command_option); if (archive < 0) open_fatal (archive_name_array[0]); /* Let's read the archive and pipe it into stdout. */ while (1) { char *cursor; size_t maximum; size_t count; size_t status; clear_read_error_count (); error_loop: status = rmtread (archive, record_start->buffer, record_size); if (status == SAFE_READ_ERROR) { archive_read_error (); goto error_loop; } if (status == 0) break; cursor = record_start->buffer; maximum = status; while (maximum) { count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE; if (full_write (STDOUT_FILENO, cursor, count) != count) write_error (use_compress_program_option); cursor += count; maximum -= count; } } xclose (STDOUT_FILENO); /* Propagate any failure of the grandchild back to the parent. */ while (waitpid (grandchild_pid, &wait_status, 0) == -1) if (errno != EINTR) { waitpid_error (use_compress_program_option); break; } if (WIFSIGNALED (wait_status)) { kill (child_pid, WTERMSIG (wait_status)); exit_status = TAREXIT_FAILURE; } else if (WEXITSTATUS (wait_status) != 0) exit_status = WEXITSTATUS (wait_status); exit (exit_status);}static voiddec_to_env (char *envar, uintmax_t num){ char buf[UINTMAX_STRSIZE_BOUND]; char *numstr; numstr = STRINGIFY_BIGINT (num, buf); if (setenv (envar, numstr, 1) != 0) xalloc_die ();}static voidtime_to_env (char *envar, struct timespec t){ char buf[TIMESPEC_STRSIZE_BOUND]; if (setenv (envar, code_timespec (t, buf), 1) != 0) xalloc_die ();}static voidoct_to_env (char *envar, unsigned long num){ char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3]; snprintf (buf, sizeof buf, "0%lo", num); if (setenv (envar, buf, 1) != 0) xalloc_die ();}static voidstr_to_env (char *envar, char const *str){ if (str) { if (setenv (envar, str, 1) != 0) xalloc_die (); } else unsetenv (envar);}static voidchr_to_env (char *envar, char c){ char buf[2]; buf[0] = c; buf[1] = 0; if (setenv (envar, buf, 1) != 0) xalloc_die ();}static voidstat_to_env (char *name, char type, struct tar_stat_info *st){ str_to_env ("TAR_VERSION", PACKAGE_VERSION); chr_to_env ("TAR_FILETYPE", type); oct_to_env ("TAR_MODE", st->stat.st_mode); str_to_env ("TAR_FILENAME", name); str_to_env ("TAR_REALNAME", st->file_name); str_to_env ("TAR_UNAME", st->uname); str_to_env ("TAR_GNAME", st->gname); time_to_env ("TAR_ATIME", st->atime); time_to_env ("TAR_MTIME", st->mtime); time_to_env ("TAR_CTIME", st->ctime); dec_to_env ("TAR_SIZE", st->stat.st_size); dec_to_env ("TAR_UID", st->stat.st_uid); dec_to_env ("TAR_GID", st->stat.st_gid); switch (type) { case 'b': case 'c': dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev)); dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev)); unsetenv ("TAR_LINKNAME"); break; case 'l': case 'h': unsetenv ("TAR_MINOR"); unsetenv ("TAR_MAJOR"); str_to_env ("TAR_LINKNAME", st->link_name); break; default: unsetenv ("TAR_MINOR"); unsetenv ("TAR_MAJOR"); unsetenv ("TAR_LINKNAME"); break; }}static pid_t global_pid;static RETSIGTYPE (*pipe_handler) (int sig);intsys_exec_command (char *file_name, int typechar, struct tar_stat_info *st){ int p[2]; char *argv[4]; xpipe (p); pipe_handler = signal (SIGPIPE, SIG_IGN); global_pid = xfork (); if (global_pid != 0) { xclose (p[PREAD]); return p[PWRITE]; } /* Child */ xdup2 (p[PREAD], STDIN_FILENO); xclose (p[PWRITE]); stat_to_env (file_name, typechar, st); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = to_command_option; argv[3] = NULL; execv ("/bin/sh", argv); exec_fatal (file_name);}voidsys_wait_command (void){ int status; if (global_pid < 0) return; signal (SIGPIPE, pipe_handler); while (waitpid (global_pid, &status, 0) == -1) if (errno != EINTR) { global_pid = -1; waitpid_error (to_command_option); return; } if (WIFEXITED (status)) { if (!ignore_command_error_option && WEXITSTATUS (status)) ERROR ((0, 0, _("%lu: Child returned status %d"), (unsigned long) global_pid, WEXITSTATUS (status))); } else if (WIFSIGNALED (status)) { WARN ((0, 0, _("%lu: Child terminated on signal %d"), (unsigned long) global_pid, WTERMSIG (status))); } else ERROR ((0, 0, _("%lu: Child terminated on unknown reason"), (unsigned long) global_pid)); global_pid = -1;}intsys_exec_info_script (const char **archive_name, int volume_number){ pid_t pid; char *argv[4]; char uintbuf[UINTMAX_STRSIZE_BOUND]; int p[2]; static RETSIGTYPE (*saved_handler) (int sig); xpipe (p); saved_handler = signal (SIGPIPE, SIG_IGN); pid = xfork (); if (pid != 0) { /* Master */ int rc; int status; char *buf = NULL; size_t size = 0; FILE *fp; xclose (p[PWRITE]); fp = fdopen (p[PREAD], "r"); rc = getline (&buf, &size, fp); fclose (fp); if (rc > 0 && buf[rc-1] == '\n') buf[--rc] = 0; while (waitpid (pid, &status, 0) == -1) if (errno != EINTR) { signal (SIGPIPE, saved_handler); waitpid_error (info_script_option); return -1; } signal (SIGPIPE, saved_handler); if (WIFEXITED (status)) { if (WEXITSTATUS (status) == 0 && rc > 0) *archive_name = buf; else free (buf); return WEXITSTATUS (status); } free (buf); return -1; } /* Child */ setenv ("TAR_VERSION", PACKAGE_VERSION, 1); setenv ("TAR_ARCHIVE", *archive_name, 1); setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1); setenv ("TAR_BLOCKING_FACTOR", STRINGIFY_BIGINT (blocking_factor, uintbuf), 1); setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1); setenv ("TAR_FORMAT", archive_format_string (current_format == DEFAULT_FORMAT ? archive_format : current_format), 1); setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1); xclose (p[PREAD]); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = (char*) info_script_option; argv[3] = NULL; execv (argv[0], argv); exec_fatal (info_script_option);}voidsys_exec_checkpoint_script (const char *script_name, const char *archive_name, int checkpoint_number){ pid_t pid; char *argv[4]; char uintbuf[UINTMAX_STRSIZE_BOUND]; pid = xfork (); if (pid != 0) { /* Master */ int status; while (waitpid (pid, &status, 0) == -1) if (errno != EINTR) { waitpid_error (script_name); break; } return; } /* Child */ setenv ("TAR_VERSION", PACKAGE_VERSION, 1); setenv ("TAR_ARCHIVE", archive_name, 1); setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1); setenv ("TAR_BLOCKING_FACTOR", STRINGIFY_BIGINT (blocking_factor, uintbuf), 1); setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1); setenv ("TAR_FORMAT", archive_format_string (current_format == DEFAULT_FORMAT ? archive_format : current_format), 1); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = (char*) script_name; argv[3] = NULL; execv (argv[0], argv); exec_fatal (script_name);}#endif /* not MSDOS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -