⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	archive = rmtopen (archive_name_array[0],			   O_RDWR | O_CREAT | O_BINARY,			   MODE_RW, rsh_command_option);	if (check_compressed_archive (NULL) != ct_none)	  FATAL_ERROR ((0, 0,			_("Cannot update compressed archives")));	break;      }  if (archive < 0      || (! _isrmt (archive) && !sys_get_archive_stat ()))    {      int saved_errno = errno;      if (backed_up_flag)	undo_last_backup ();      errno = saved_errno;      open_fatal (archive_name_array[0]);    }  sys_detect_dev_null_output ();  sys_save_archive_dev_ino ();  SET_BINARY_MODE (archive);  switch (wanted_access)    {    case ACCESS_READ:      find_next_block ();	/* read it in, check for EOF */      break;    case ACCESS_UPDATE:    case ACCESS_WRITE:      records_written = 0;      break;    }}/* Perform a write to flush the buffer.  */ssize_t_flush_write (void){  ssize_t status;  checkpoint_run (true);  if (tape_length_option && tape_length_option <= bytes_written)    {      errno = ENOSPC;      status = 0;    }  else if (dev_null_output)    status = record_size;  else    status = sys_write_archive_buffer ();    return status;}/* Handle write errors on the archive.  Write errors are always fatal.   Hitting the end of a volume does not cause a write error unless the   write was the first record of the volume.  */voidarchive_write_error (ssize_t status){  /* It might be useful to know how much was written before the error     occurred.  */  if (totals_option)    {      int e = errno;      print_total_stats ();      errno = e;    }  write_fatal_details (*archive_name_cursor, status, record_size);}/* Handle read errors on the archive.  If the read should be retried,   return to the caller.  */voidarchive_read_error (void){  read_error (*archive_name_cursor);  if (record_start_block == 0)    FATAL_ERROR ((0, 0, _("At beginning of tape, quitting now")));  /* Read error in mid archive.  We retry up to READ_ERROR_MAX times and     then give up on reading the archive.  */  if (read_error_count++ > READ_ERROR_MAX)    FATAL_ERROR ((0, 0, _("Too many errors, quitting")));  return;}static voidshort_read (size_t status){  size_t left;			/* bytes left */  char *more;			/* pointer to next byte to read */  more = record_start->buffer + status;  left = record_size - status;  while (left % BLOCKSIZE != 0	 || (left && status && read_full_records))    {      if (status)	while ((status = rmtread (archive, more, left)) == SAFE_READ_ERROR)	  archive_read_error ();      if (status == 0)	break;      if (! read_full_records)	{	  unsigned long rest = record_size - left;	  FATAL_ERROR ((0, 0,			ngettext ("Unaligned block (%lu byte) in archive",				  "Unaligned block (%lu bytes) in archive",				  rest),			rest));	}      /* User warned us about this.  Fix up.  */      left -= status;      more += status;    }  /* FIXME: for size=0, multi-volume support.  On the first record, warn     about the problem.  */  if (!read_full_records && verbose_option > 1      && record_start_block == 0 && status != 0)    {      unsigned long rsize = (record_size - left) / BLOCKSIZE;      WARN ((0, 0,	     ngettext ("Record size = %lu block",		       "Record size = %lu blocks",		       rsize),	     rsize));    }  record_end = record_start + (record_size - left) / BLOCKSIZE;  records_read++;}/*  Flush the current buffer to/from the archive.  */voidflush_archive (void){  size_t buffer_level = current_block->buffer - record_start->buffer;  record_start_block += record_end - record_start;  current_block = record_start;  record_end = record_start + blocking_factor;  if (access_mode == ACCESS_READ && time_to_start_writing)    {      access_mode = ACCESS_WRITE;      time_to_start_writing = false;      backspace_output ();    }  switch (access_mode)    {    case ACCESS_READ:      flush_read ();      break;    case ACCESS_WRITE:      flush_write_ptr (buffer_level);      break;    case ACCESS_UPDATE:      abort ();    }}/* Backspace the archive descriptor by one record worth.  If it's a   tape, MTIOCTOP will work.  If it's something else, try to seek on   it.  If we can't seek, we lose!  */static voidbackspace_output (void){#ifdef MTIOCTOP  {    struct mtop operation;    operation.mt_op = MTBSR;    operation.mt_count = 1;    if (rmtioctl (archive, MTIOCTOP, (char *) &operation) >= 0)      return;    if (errno == EIO && rmtioctl (archive, MTIOCTOP, (char *) &operation) >= 0)      return;  }#endif  {    off_t position = rmtlseek (archive, (off_t) 0, SEEK_CUR);    /* Seek back to the beginning of this record and start writing there.  */    position -= record_size;    if (position < 0)      position = 0;    if (rmtlseek (archive, position, SEEK_SET) != position)      {	/* Lseek failed.  Try a different method.  */	WARN ((0, 0,	       _("Cannot backspace archive file; it may be unreadable without -i")));	/* Replace the first part of the record with NULs.  */	if (record_start->buffer != output_start)	  memset (record_start->buffer, 0,		  output_start - record_start->buffer);      }  }}off_tseek_archive (off_t size){  off_t start = current_block_ordinal ();  off_t offset;  off_t nrec, nblk;  off_t skipped = (blocking_factor - (current_block - record_start));  size -= skipped * BLOCKSIZE;  if (size < record_size)    return 0;  /* FIXME: flush? */  /* Compute number of records to skip */  nrec = size / record_size;  offset = rmtlseek (archive, nrec * record_size, SEEK_CUR);  if (offset < 0)    return offset;  if (offset % record_size)    FATAL_ERROR ((0, 0, _("rmtlseek not stopped at a record boundary")));  /* Convert to number of records */  offset /= BLOCKSIZE;  /* Compute number of skipped blocks */  nblk = offset - start;  /* Update buffering info */  records_read += nblk / blocking_factor;  record_start_block = offset - blocking_factor;  current_block = record_end;  return nblk;}/* Close the archive file.  */voidclose_archive (void){  if (time_to_start_writing || access_mode == ACCESS_WRITE)    {      flush_archive ();      if (current_block > record_start)	flush_archive ();    }  sys_drain_input_pipe ();  compute_duration ();  if (verify_option)    verify_volume ();  if (rmtclose (archive) != 0)    close_error (*archive_name_cursor);  sys_wait_for_child (child_pid);  tar_stat_destroy (&current_stat_info);  if (save_name)    free (save_name);  if (real_s_name)    free (real_s_name);  free (record_buffer[0]);  free (record_buffer[1]);}/* Called to initialize the global volume number.  */voidinit_volume_number (void){  FILE *file = fopen (volno_file_option, "r");  if (file)    {      if (fscanf (file, "%d", &global_volno) != 1	  || global_volno < 0)	FATAL_ERROR ((0, 0, _("%s: contains invalid volume number"),		      quotearg_colon (volno_file_option)));      if (ferror (file))	read_error (volno_file_option);      if (fclose (file) != 0)	close_error (volno_file_option);    }  else if (errno != ENOENT)    open_error (volno_file_option);}/* Called to write out the closing global volume number.  */voidcloseout_volume_number (void){  FILE *file = fopen (volno_file_option, "w");  if (file)    {      fprintf (file, "%d\n", global_volno);      if (ferror (file))	write_error (volno_file_option);      if (fclose (file) != 0)	close_error (volno_file_option);    }  else    open_error (volno_file_option);}static voidincrease_volume_number (){  global_volno++;  if (global_volno < 0)    FATAL_ERROR ((0, 0, _("Volume number overflow")));  volno++;}voidchange_tape_menu (FILE *read_file){  char *input_buffer = NULL;  size_t size = 0;  bool stop = false;    while (!stop)    {      fputc ('\007', stderr);      fprintf (stderr,	       _("Prepare volume #%d for %s and hit return: "),	       global_volno + 1, quote (*archive_name_cursor));      fflush (stderr);      if (getline (&input_buffer, &size, read_file) <= 0)	{	  WARN ((0, 0, _("EOF where user reply was expected")));	  if (subcommand_option != EXTRACT_SUBCOMMAND	      && subcommand_option != LIST_SUBCOMMAND	      && subcommand_option != DIFF_SUBCOMMAND)	    WARN ((0, 0, _("WARNING: Archive is incomplete")));	  fatal_exit ();	}      if (input_buffer[0] == '\n'	  || input_buffer[0] == 'y'	  || input_buffer[0] == 'Y')	break;      switch (input_buffer[0])	{	case '?':	  {	    fprintf (stderr, _("\ n name        Give a new file name for the next (and subsequent) volume(s)\n\ q             Abort tar\n\ y or newline  Continue operation\n"));            if (!restrict_option)              fprintf (stderr, _(" !             Spawn a subshell\n"));	    fprintf (stderr, _(" ?             Print this list\n"));	  }	  break;	case 'q':	  /* Quit.  */	  WARN ((0, 0, _("No new volume; exiting.\n")));	  if (subcommand_option != EXTRACT_SUBCOMMAND	      && subcommand_option != LIST_SUBCOMMAND	      && subcommand_option != DIFF_SUBCOMMAND)	    WARN ((0, 0, _("WARNING: Archive is incomplete")));	  fatal_exit ();	case 'n':	  /* Get new file name.  */	  {	    char *name;	    char *cursor;	    for (name = input_buffer + 1;		 *name == ' ' || *name == '\t';		 name++)	      ;	    for (cursor = name; *cursor && *cursor != '\n'; cursor++)	      ;	    *cursor = '\0';	    if (name[0])	      {		/* FIXME: the following allocation is never reclaimed.  */		*archive_name_cursor = xstrdup (name);		stop = true;	      }	    else	      fprintf (stderr, "%s",		       _("File name not specified. Try again.\n"));	  }	  break;	case '!':	  if (!restrict_option)	    {	      sys_spawn_shell ();	      break;	    }	  /* FALL THROUGH */	default:	  fprintf (stderr, _("Invalid input. Type ? for help.\n"));	}    }  free (input_buffer);}/* We've hit the end of the old volume.  Close it and open the next one.   Return nonzero on success.*/static boolnew_volume (enum access_mode mode){  static FILE *read_file;  static int looped;  int prompt;  if (!read_file && !info_script_option)    /* FIXME: if fopen is used, it will never be closed.  */    read_file = archive == STDIN_FILENO ? fopen (TTY_NAME, "r") : stdin;  if (now_verifying)    return false;  if (verify_option)    verify_volume ();  assign_string (&volume_label, NULL);  assign_string (&continued_file_name, NULL);  continued_file_size = continued_file_offset = 0;  current_block = record_start;    if (rmtclose (archive) != 0)    close_error (*archive_name_cursor);  archive_name_cursor++;  if (archive_name_cursor == archive_name_array + archive_names)    {      archive_name_cursor = archive_name_array;      looped = 1;    }  prompt = looped; tryagain:  if (prompt)    {      /* We have to prompt from now on.  */      if (info_script_option)	{	  if (volno_file_option)	    closeout_volume_number ();	  if (sys_exec_info_script (archive_name_cursor, global_volno+1))	    FATAL_ERROR ((0, 0, _("%s command failed"),			  quote (info_script_option)));	}      else	change_tape_menu (read_file);    }  if (strcmp (archive_name_cursor[0], "-") == 0)    {      read_full_records = true;      archive = STDIN_FILENO;    }  else if (verify_option)    archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,		       rsh_command_option);  else    switch (mode)      {      case ACCESS_READ:	archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,			   rsh_command_option);	break;      case ACCESS_WRITE:	if (backup_option)	  maybe_backup_file (*archive_name_cursor, 1);	archive = rmtcreat (*archive_name_cursor, MODE_RW,			    rsh_command_option);	break;      case ACCESS_UPDATE:	archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,			   rsh_command_option);	break;      }  if (archive < 0)    {      open_warn (*archive_name_cursor);      if (!verify_option && mode == ACCESS_WRITE && backup_option)	undo_last_backup ();      prompt = 1;      goto tryagain;    }  SET_BINARY_MODE (archive);  return true;}static boolread_header0 (struct tar_stat_info *info){  enum read_header rc;  tar_stat_init (info);  rc = read_header_primitive (false, info);  if (rc == HEADER_SUCCESS)    {      set_next_block_after (current_header);      return true;    }  ERROR ((0, 0, _("This does not look like a tar archive")));  return false;}booltry_new_volume (){  size_t status;  union block *header;  enum access_mode acc;    switch (subcommand_option)    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -