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

📄 sparse.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 3 页
字号:
      && h->star_in_header.sp[0].offset[10] != '\0')    {      /* Old star format */      for (i = 0; i < SPARSES_IN_STAR_HEADER; i++)	{	  rc = oldgnu_add_sparse (file, &h->star_in_header.sp[i]);	  if (rc != add_ok)	    break;	}      ext_p = h->star_in_header.isextended;    }  else    ext_p = 1;  for (; rc == add_ok && ext_p; ext_p = h->star_ext_header.isextended)    {      h = find_next_block ();      if (!h)	{	  ERROR ((0, 0, _("Unexpected EOF in archive")));	  return false;	}      set_next_block_after (h);      for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)	rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);    }  if (rc == add_fail)    {      ERROR ((0, 0, _("%s: invalid sparse archive member"),	      file->stat_info->orig_file_name));      return false;    }  return true;}static struct tar_sparse_optab const star_optab = {  NULL,  /* No init function */  NULL,  /* No done function */  star_sparse_member_p,  NULL,  star_fixup_header,  star_get_sparse_info,  NULL,  /* No scan_block function */  NULL, /* No dump region function */  sparse_extract_region,};/* GNU PAX sparse file format. There are several versions:   * 0.0   The initial version of sparse format used by tar 1.14-1.15.1.   The sparse file map is stored in x header:   GNU.sparse.size      Real size of the stored file   GNU.sparse.numblocks Number of blocks in the sparse map   repeat numblocks time     GNU.sparse.offset    Offset of the next data block     GNU.sparse.numbytes  Size of the next data block   end repeat   This has been reported as conflicting with the POSIX specs. The reason is   that offsets and sizes of non-zero data blocks were stored in multiple   instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas   POSIX requires the latest occurrence of the variable to override all   previous occurrences.      To avoid this incompatibility two following versions were introduced.   * 0.1   Used by tar 1.15.2 -- 1.15.91 (alpha releases).      The sparse file map is stored in   x header:   GNU.sparse.size      Real size of the stored file   GNU.sparse.numblocks Number of blocks in the sparse map   GNU.sparse.map       Map of non-null data chunks. A string consisting                       of comma-separated values "offset,size[,offset,size]..."   The resulting GNU.sparse.map string can be *very* long. While POSIX does not   impose any limit on the length of a x header variable, this can confuse some   tars.   * 1.0   Starting from this version, the exact sparse format version is specified   explicitely in the header using the following variables:   GNU.sparse.major     Major version    GNU.sparse.minor     Minor version   X header keeps the following variables:      GNU.sparse.name      Real file name of the sparse file   GNU.sparse.realsize  Real size of the stored file (corresponds to the old                        GNU.sparse.size variable)   The name field of the ustar header is constructed using the pattern   "%d/GNUSparseFile.%p/%f".      The sparse map itself is stored in the file data block, preceding the actual   file data. It consists of a series of octal numbers of arbitrary length,   delimited by newlines. The map is padded with nulls to the nearest block   boundary.   The first number gives the number of entries in the map. Following are map   entries, each one consisting of two numbers giving the offset and size of   the data block it describes.   The format is designed in such a way that non-posix aware tars and tars not   supporting GNU.sparse.* keywords will extract each sparse file in its   condensed form with the file map attached and will place it into a separate   directory. Then, using a simple program it would be possible to expand the   file to its original form even without GNU tar.   Bu default, v.1.0 archives are created. To use other formats,   --sparse-version option is provided. Additionally, v.0.0 can be obtained   by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1   --pax-option delete=GNU.sparse.map*/static boolpax_sparse_member_p (struct tar_sparse_file *file){  return file->stat_info->sparse_map_avail > 0          || file->stat_info->sparse_major > 0;}static boolpax_dump_header_0 (struct tar_sparse_file *file){  off_t block_ordinal = current_block_ordinal ();  union block *blk;  size_t i;  char nbuf[UINTMAX_STRSIZE_BOUND];  struct sp_array *map = file->stat_info->sparse_map;  char *save_file_name = NULL;    /* Store the real file size */  xheader_store ("GNU.sparse.size", file->stat_info, NULL);  xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);    if (xheader_keyword_deleted_p ("GNU.sparse.map")      || tar_sparse_minor == 0)    {      for (i = 0; i < file->stat_info->sparse_map_avail; i++)	{	  xheader_store ("GNU.sparse.offset", file->stat_info, &i);	  xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);	}    }  else    {      xheader_store ("GNU.sparse.name", file->stat_info, NULL);      save_file_name = file->stat_info->file_name;      file->stat_info->file_name = xheader_format_name (file->stat_info,					       "%d/GNUSparseFile.%p/%f", 0);      xheader_string_begin (&file->stat_info->xhdr);      for (i = 0; i < file->stat_info->sparse_map_avail; i++)	{	  if (i)	    xheader_string_add (&file->stat_info->xhdr, ",");	  xheader_string_add (&file->stat_info->xhdr,			      umaxtostr (map[i].offset, nbuf));	  xheader_string_add (&file->stat_info->xhdr, ",");	  xheader_string_add (&file->stat_info->xhdr,			      umaxtostr (map[i].numbytes, nbuf));	}      if (!xheader_string_end (&file->stat_info->xhdr,			       "GNU.sparse.map"))	{	  free (file->stat_info->file_name);	  file->stat_info->file_name = save_file_name;	  return false;	}    }  blk = start_header (file->stat_info);  /* Store the effective (shrunken) file size */  OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);  finish_header (file->stat_info, blk, block_ordinal);  if (save_file_name)    {      free (file->stat_info->file_name);      file->stat_info->file_name = save_file_name;    }  return true;}static boolpax_dump_header_1 (struct tar_sparse_file *file){  off_t block_ordinal = current_block_ordinal ();  union block *blk;  char *p, *q;  size_t i;  char nbuf[UINTMAX_STRSIZE_BOUND];  off_t size = 0;  struct sp_array *map = file->stat_info->sparse_map;  char *save_file_name = file->stat_info->file_name;#define COPY_STRING(b,dst,src) do                \ {                                               \   char *endp = b->buffer + BLOCKSIZE;           \   char *srcp = src;                             \   while (*srcp)                                 \     {                                           \       if (dst == endp)                          \	 {                                       \	   set_next_block_after (b);             \	   b = find_next_block ();               \           dst = b->buffer;                      \	   endp = b->buffer + BLOCKSIZE;         \	 }                                       \       *dst++ = *srcp++;                         \     }                                           \   } while (0)                         /* Compute stored file size */  p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);  size += strlen (p) + 1;  for (i = 0; i < file->stat_info->sparse_map_avail; i++)    {      p = umaxtostr (map[i].offset, nbuf);      size += strlen (p) + 1;      p = umaxtostr (map[i].numbytes, nbuf);      size += strlen (p) + 1;    }  size = (size + BLOCKSIZE - 1) / BLOCKSIZE;  file->stat_info->archive_file_size += size * BLOCKSIZE;  file->dumped_size += size * BLOCKSIZE;    /* Store sparse file identification */  xheader_store ("GNU.sparse.major", file->stat_info, NULL);  xheader_store ("GNU.sparse.minor", file->stat_info, NULL);  xheader_store ("GNU.sparse.name", file->stat_info, NULL);  xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);    file->stat_info->file_name = xheader_format_name (file->stat_info,					    "%d/GNUSparseFile.%p/%f", 0);  blk = start_header (file->stat_info);  /* Store the effective (shrunken) file size */  OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);  finish_header (file->stat_info, blk, block_ordinal);  free (file->stat_info->file_name);  file->stat_info->file_name = save_file_name;  blk = find_next_block ();  q = blk->buffer;  p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);  COPY_STRING (blk, q, p);  COPY_STRING (blk, q, "\n");  for (i = 0; i < file->stat_info->sparse_map_avail; i++)    {      p = umaxtostr (map[i].offset, nbuf);      COPY_STRING (blk, q, p);      COPY_STRING (blk, q, "\n");      p = umaxtostr (map[i].numbytes, nbuf);      COPY_STRING (blk, q, p);      COPY_STRING (blk, q, "\n");    }  memset (q, 0, BLOCKSIZE - (q - blk->buffer));  set_next_block_after (blk);  return true;}static boolpax_dump_header (struct tar_sparse_file *file){  file->stat_info->sparse_major = tar_sparse_major;  file->stat_info->sparse_minor = tar_sparse_minor;  return (file->stat_info->sparse_major == 0) ?           pax_dump_header_0 (file) : pax_dump_header_1 (file);}static booldecode_num (uintmax_t *num, char const *arg, uintmax_t maxval){  uintmax_t u;  char *arg_lim;  if (!ISDIGIT (*arg))    return false;    u = strtoumax (arg, &arg_lim, 10);  if (! (u <= maxval && errno != ERANGE) || *arg_lim)    return false;    *num = u;  return true;}static boolpax_decode_header (struct tar_sparse_file *file){  if (file->stat_info->sparse_major > 0)    {      uintmax_t u;      char nbuf[UINTMAX_STRSIZE_BOUND];      union block *blk;      char *p;      size_t i;#define COPY_BUF(b,buf,src) do                                     \ {                                                                 \   char *endp = b->buffer + BLOCKSIZE;                             \   char *dst = buf;                                                \   do                                                              \     {                                                             \       if (dst == buf + UINTMAX_STRSIZE_BOUND -1)                  \         {                                                         \           ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \	          file->stat_info->orig_file_name));               \           return false;                                           \         }                                                         \       if (src == endp)                                            \	 {                                                         \	   set_next_block_after (b);                               \           file->dumped_size += BLOCKSIZE;                         \           b = find_next_block ();                                 \           src = b->buffer;                                        \	   endp = b->buffer + BLOCKSIZE;                           \	 }                                                         \       *dst = *src++;                                              \     }                                                             \   while (*dst++ != '\n');                                         \   dst[-1] = 0;                                                    \ } while (0)                             set_next_block_after (current_header);      file->dumped_size += BLOCKSIZE;      blk = find_next_block ();      p = blk->buffer;      COPY_BUF (blk,nbuf,p);      if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))	{	  ERROR ((0, 0, _("%s: malformed sparse archive member"), 		  file->stat_info->orig_file_name));	  return false;	}      file->stat_info->sparse_map_size = u;      file->stat_info->sparse_map = xcalloc (file->stat_info->sparse_map_size,					     sizeof (*file->stat_info->sparse_map));      file->stat_info->sparse_map_avail = 0;      for (i = 0; i < file->stat_info->sparse_map_size; i++)	{	  struct sp_array sp;	  	  COPY_BUF (blk,nbuf,p);	  if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))	    {	      ERROR ((0, 0, _("%s: malformed sparse archive member"), 		      file->stat_info->orig_file_name));	      return false;	    }	  sp.offset = u;	  COPY_BUF (blk,nbuf,p);	  if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))	    {	      ERROR ((0, 0, _("%s: malformed sparse archive member"), 		      file->stat_info->orig_file_name));	      return false;	    }	  sp.numbytes = u;	  sparse_add_map (file->stat_info, &sp);	}      set_next_block_after (blk);    }    return true;}static struct tar_sparse_optab const pax_optab = {  NULL,  /* No init function */  NULL,  /* No done function */  pax_sparse_member_p,  pax_dump_header,  NULL,  pax_decode_header,    NULL,  /* No scan_block function */  sparse_dump_region,  sparse_extract_region,};

⌨️ 快捷键说明

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