📄 rtapelib.c
字号:
for (remote_pipe_number = 0; remote_pipe_number < MAXUNIT; remote_pipe_number++) if (READ_SIDE (remote_pipe_number) == -1 && WRITE_SIDE (remote_pipe_number) == -1) break; if (remote_pipe_number == MAXUNIT) { errno = EMFILE; return -1; } /* Pull apart the system and device, and optional user. */ { char *cursor; file_name_copy = xstrdup (file_name); remote_host = file_name_copy; remote_user = 0; remote_file = 0; for (cursor = file_name_copy; *cursor; cursor++) switch (*cursor) { default: break; case '\n': /* Do not allow newlines in the file_name, since the protocol uses newline delimiters. */ free (file_name_copy); errno = ENOENT; return -1; case '@': if (!remote_user) { remote_user = remote_host; *cursor = '\0'; remote_host = cursor + 1; } break; case ':': if (!remote_file) { *cursor = '\0'; remote_file = cursor + 1; } break; } } /* FIXME: Should somewhat validate the decoding, here. */ if (remote_user && *remote_user == '\0') remote_user = 0;#if WITH_REXEC /* Execute the remote command using rexec. */ READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user); if (READ_SIDE (remote_pipe_number) < 0) { int e = errno; free (file_name_copy); errno = e; return -1; } WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);#else /* not WITH_REXEC */ { const char *remote_shell_basename; pid_t status; /* Identify the remote command to be executed. */ if (!remote_shell) {#ifdef REMOTE_SHELL remote_shell = REMOTE_SHELL;#else free (file_name_copy); errno = EIO; return -1;#endif } remote_shell_basename = last_component (remote_shell); /* Set up the pipes for the `rsh' command, and fork. */ if (pipe (to_remote[remote_pipe_number]) == -1 || pipe (from_remote[remote_pipe_number]) == -1) { int e = errno; free (file_name_copy); errno = e; return -1; } status = fork (); if (status == -1) { int e = errno; free (file_name_copy); errno = e; return -1; } if (status == 0) { /* Child. */ close (STDIN_FILENO); dup (to_remote[remote_pipe_number][PREAD]); close (to_remote[remote_pipe_number][PREAD]); close (to_remote[remote_pipe_number][PWRITE]); close (STDOUT_FILENO); dup (from_remote[remote_pipe_number][PWRITE]); close (from_remote[remote_pipe_number][PREAD]); close (from_remote[remote_pipe_number][PWRITE]); sys_reset_uid_gid (); if (remote_user) execl (remote_shell, remote_shell_basename, remote_host, "-l", remote_user, rmt_command, (char *) 0); else execl (remote_shell, remote_shell_basename, remote_host, rmt_command, (char *) 0); /* Bad problems if we get here. */ /* In a previous version, _exit was used here instead of exit. */ error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell")); } /* Parent. */ close (from_remote[remote_pipe_number][PWRITE]); close (to_remote[remote_pipe_number][PREAD]); }#endif /* not WITH_REXEC */ /* Attempt to open the tape device. */ { size_t remote_file_len = strlen (remote_file); char *command_buffer = xmalloc (remote_file_len + 1000); sprintf (command_buffer, "O%s\n", remote_file); encode_oflag (command_buffer + remote_file_len + 2, open_mode); strcat (command_buffer, "\n"); if (do_command (remote_pipe_number, command_buffer) == -1 || get_status (remote_pipe_number) == -1) { int e = errno; free (command_buffer); free (file_name_copy); _rmt_shutdown (remote_pipe_number, e); return -1; } free (command_buffer); } free (file_name_copy); return remote_pipe_number + bias;}/* Close remote tape connection HANDLE and shut down. Return 0 if successful, -1 on error. */intrmt_close__ (int handle){ long int status; if (do_command (handle, "C\n") == -1) return -1; status = get_status (handle); _rmt_shutdown (handle, errno); return status;}/* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE. Return the number of bytes read on success, SAFE_READ_ERROR on error. */size_trmt_read__ (int handle, char *buffer, size_t length){ char command_buffer[COMMAND_BUFFER_SIZE]; size_t status; size_t rlen; size_t counter; sprintf (command_buffer, "R%lu\n", (unsigned long) length); if (do_command (handle, command_buffer) == -1 || (status = get_status (handle)) == SAFE_READ_ERROR) return SAFE_READ_ERROR; for (counter = 0; counter < status; counter += rlen, buffer += rlen) { rlen = safe_read (READ_SIDE (handle), buffer, status - counter); if (rlen == SAFE_READ_ERROR || rlen == 0) { _rmt_shutdown (handle, EIO); return SAFE_READ_ERROR; } } return status;}/* Write LENGTH bytes from BUFFER to remote tape connection HANDLE. Return the number of bytes written. */size_trmt_write__ (int handle, char *buffer, size_t length){ char command_buffer[COMMAND_BUFFER_SIZE]; RETSIGTYPE (*pipe_handler) (); size_t written; sprintf (command_buffer, "W%lu\n", (unsigned long) length); if (do_command (handle, command_buffer) == -1) return 0; pipe_handler = signal (SIGPIPE, SIG_IGN); written = full_write (WRITE_SIDE (handle), buffer, length); signal (SIGPIPE, pipe_handler); if (written == length) { long int r = get_status (handle); if (r < 0) return 0; if (r == length) return length; written = r; } /* Write error. */ _rmt_shutdown (handle, EIO); return written;}/* Perform an imitation lseek operation on remote tape connection HANDLE. Return the new file offset if successful, -1 if on error. */off_trmt_lseek__ (int handle, off_t offset, int whence){ char command_buffer[COMMAND_BUFFER_SIZE]; char operand_buffer[UINTMAX_STRSIZE_BOUND]; uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset; char *p = operand_buffer + sizeof operand_buffer; *--p = 0; do *--p = '0' + (int) (u % 10); while ((u /= 10) != 0); if (offset < 0) *--p = '-'; switch (whence) { case SEEK_SET: whence = 0; break; case SEEK_CUR: whence = 1; break; case SEEK_END: whence = 2; break; default: abort (); } sprintf (command_buffer, "L%s\n%d\n", p, whence); if (do_command (handle, command_buffer) == -1) return -1; return get_status_off (handle);}/* Perform a raw tape operation on remote tape connection HANDLE. Return the results of the ioctl, or -1 on error. */intrmt_ioctl__ (int handle, int operation, char *argument){ switch (operation) { default: errno = EOPNOTSUPP; return -1;#ifdef MTIOCTOP case MTIOCTOP: { char command_buffer[COMMAND_BUFFER_SIZE]; char operand_buffer[UINTMAX_STRSIZE_BOUND]; uintmax_t u = (((struct mtop *) argument)->mt_count < 0 ? - (uintmax_t) ((struct mtop *) argument)->mt_count : (uintmax_t) ((struct mtop *) argument)->mt_count); char *p = operand_buffer + sizeof operand_buffer; *--p = 0; do *--p = '0' + (int) (u % 10); while ((u /= 10) != 0); if (((struct mtop *) argument)->mt_count < 0) *--p = '-'; /* MTIOCTOP is the easy one. Nothing is transferred in binary. */ sprintf (command_buffer, "I%d\n%s\n", ((struct mtop *) argument)->mt_op, p); if (do_command (handle, command_buffer) == -1) return -1; return get_status (handle); }#endif /* MTIOCTOP */#ifdef MTIOCGET case MTIOCGET: { ssize_t status; size_t counter; /* Grab the status and read it directly into the structure. This assumes that the status buffer is not padded and that 2 shorts fit in a long without any word alignment problems; i.e., the whole struct is contiguous. NOTE - this is probably NOT a good assumption. */ if (do_command (handle, "S") == -1 || (status = get_status (handle), status == -1)) return -1; for (; status > 0; status -= counter, argument += counter) { counter = safe_read (READ_SIDE (handle), argument, status); if (counter == SAFE_READ_ERROR || counter == 0) { _rmt_shutdown (handle, EIO); return -1; } } /* Check for byte position. mt_type (or mt_model) is a small integer field (normally) so we will check its magnitude. If it is larger than 256, we will assume that the bytes are swapped and go through and reverse all the bytes. */ if (((struct mtget *) argument)->MTIO_CHECK_FIELD < 256) return 0; for (counter = 0; counter < status; counter += 2) { char copy = argument[counter]; argument[counter] = argument[counter + 1]; argument[counter + 1] = copy; } return 0; }#endif /* MTIOCGET */ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -