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

📄 xheader.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* POSIX extended headers for tar.   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.   This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the   Free Software Foundation; either version 3, or (at your option) any later   version.   This program is distributed in the hope that it will be useful, but   WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General   Public License for more details.   You should have received a copy of the GNU General Public License along   with this program; if not, write to the Free Software Foundation, Inc.,   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */#include <system.h>#include <fnmatch.h>#include <hash.h>#include <inttostr.h>#include <quotearg.h>#include "common.h"#include <fnmatch.h>static bool xheader_protected_pattern_p (char const *pattern);static bool xheader_protected_keyword_p (char const *keyword);static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));/* Used by xheader_finish() */static void code_string (char const *string, char const *keyword,			 struct xheader *xhdr);/* Number of global headers written so far. */static size_t global_header_count;/* FIXME: Possibly it should be reset after changing the volume.   POSIX %n specification says that it is expanded to the sequence   number of current global header in *the* archive. However, for   multi-volume archives this will yield duplicate header names   in different volumes, which I'd like to avoid. The best way   to solve this would be to use per-archive header count as required   by POSIX *and* set globexthdr.name to, say,   $TMPDIR/GlobalHead.%p.$NUMVOLUME.%n.   However it should wait until buffer.c is finally rewritten *//* Interface functions to obstacks */static voidx_obstack_grow (struct xheader *xhdr, const char *ptr, size_t length){  obstack_grow (xhdr->stk, ptr, length);  xhdr->size += length;}static voidx_obstack_1grow (struct xheader *xhdr, char c){  obstack_1grow (xhdr->stk, c);  xhdr->size++;}static voidx_obstack_blank (struct xheader *xhdr, size_t length){  obstack_blank (xhdr->stk, length);  xhdr->size += length;}/* Keyword options */struct keyword_list{  struct keyword_list *next;  char *pattern;  char *value;};/* List of keyword patterns set by delete= option */static struct keyword_list *keyword_pattern_list;/* List of keyword/value pairs set by `keyword=value' option */static struct keyword_list *keyword_global_override_list;/* List of keyword/value pairs set by `keyword:=value' option */static struct keyword_list *keyword_override_list;/* List of keyword/value pairs decoded from the last 'g' type header */static struct keyword_list *global_header_override_list;/* Template for the name field of an 'x' type header */static char *exthdr_name;/* Template for the name field of a 'g' type header */static char *globexthdr_name;boolxheader_keyword_deleted_p (const char *kw){  struct keyword_list *kp;  for (kp = keyword_pattern_list; kp; kp = kp->next)    if (fnmatch (kp->pattern, kw, 0) == 0)      return true;  return false;}static boolxheader_keyword_override_p (const char *keyword){  struct keyword_list *kp;  for (kp = keyword_override_list; kp; kp = kp->next)    if (strcmp (kp->pattern, keyword) == 0)      return true;  return false;}static voidxheader_list_append (struct keyword_list **root, char const *kw,		     char const *value){  struct keyword_list *kp = xmalloc (sizeof *kp);  kp->pattern = xstrdup (kw);  kp->value = value ? xstrdup (value) : NULL;  kp->next = *root;  *root = kp;}static voidxheader_list_destroy (struct keyword_list **root){  if (root)    {      struct keyword_list *kw = *root;      while (kw)	{	  struct keyword_list *next = kw->next;	  free (kw->pattern);	  free (kw->value);	  free (kw);	  kw = next;	}      *root = NULL;    }}static voidxheader_set_single_keyword (char *kw){  USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));}static voidxheader_set_keyword_equal (char *kw, char *eq){  bool global = true;  char *p = eq;  if (eq[-1] == ':')    {      p--;      global = false;    }  while (p > kw && isspace (*p))    p--;  *p = 0;  for (p = eq + 1; *p && isspace (*p); p++)    ;  if (strcmp (kw, "delete") == 0)    {      if (xheader_protected_pattern_p (p))	USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p)));      xheader_list_append (&keyword_pattern_list, p, NULL);    }  else if (strcmp (kw, "exthdr.name") == 0)    assign_string (&exthdr_name, p);  else if (strcmp (kw, "globexthdr.name") == 0)    assign_string (&globexthdr_name, p);  else    {      if (xheader_protected_keyword_p (kw))	USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw));      if (global)	xheader_list_append (&keyword_global_override_list, kw, p);      else	xheader_list_append (&keyword_override_list, kw, p);    }}voidxheader_set_option (char *string){  char *token;  for (token = strtok (string, ","); token; token = strtok (NULL, ","))    {      char *p = strchr (token, '=');      if (!p)	xheader_set_single_keyword (token);      else	xheader_set_keyword_equal (token, p);    }}/*    string Includes:          Replaced By:     %d                       The directory name of the file,                              equivalent to the result of the                              dirname utility on the translated                              file name.     %f                       The filename of the file, equivalent                              to the result of the basename                              utility on the translated file name.     %p                       The process ID of the pax process.     %n                       The value of the 3rd argument.     %%                       A '%' character. */char *xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n){  char *buf;  size_t len = strlen (fmt);  char *q;  const char *p;  char *dirp = NULL;  char *dir = NULL;  char *base = NULL;  char pidbuf[UINTMAX_STRSIZE_BOUND];  char const *pptr;  char nbuf[UINTMAX_STRSIZE_BOUND];  char const *nptr = NULL;  for (p = fmt; *p && (p = strchr (p, '%')); )    {      switch (p[1])	{	case '%':	  len--;	  break;	case 'd':	  if (st)	    {	      if (!dirp)		dirp = dir_name (st->orig_file_name);	      dir = safer_name_suffix (dirp, false, absolute_names_option);	      len += strlen (dir) - 2;	    }	  break;	case 'f':	  if (st)	    {	      base = last_component (st->orig_file_name);	      len += strlen (base) - 2;	    }	  break;	case 'p':	  pptr = umaxtostr (getpid (), pidbuf);	  len += pidbuf + sizeof pidbuf - 1 - pptr - 2;	  break;	case 'n':	  nptr = umaxtostr (n, nbuf);	  len += nbuf + sizeof nbuf - 1 - nptr - 2;	  break;	}      p++;    }  buf = xmalloc (len + 1);  for (q = buf, p = fmt; *p; )    {      if (*p == '%')	{	  switch (p[1])	    {	    case '%':	      *q++ = *p++;	      p++;	      break;	    case 'd':	      if (dir)		q = stpcpy (q, dir);	      p += 2;	      break;	    case 'f':	      if (base)		q = stpcpy (q, base);	      p += 2;	      break;	    case 'p':	      q = stpcpy (q, pptr);	      p += 2;	      break;	    case 'n':	      if (nptr)		{		  q = stpcpy (q, nptr);		  p += 2;		  break;		}	      /* else fall through */	    default:	      *q++ = *p++;	      if (*p)		*q++ = *p++;	    }	}      else	*q++ = *p++;    }  free (dirp);  /* Do not allow it to end in a slash */  while (q > buf && ISSLASH (q[-1]))    q--;  *q = 0;  return buf;}char *xheader_xhdr_name (struct tar_stat_info *st){  if (!exthdr_name)    assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");  return xheader_format_name (st, exthdr_name, 0);}#define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"char *xheader_ghdr_name (void){  if (!globexthdr_name)    {      size_t len;      const char *tmp = getenv ("TMPDIR");      if (!tmp)	tmp = "/tmp";      len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */      globexthdr_name = xmalloc (len);      strcpy(globexthdr_name, tmp);      strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);    }  return xheader_format_name (NULL, globexthdr_name, global_header_count + 1);}voidxheader_write (char type, char *name, struct xheader *xhdr){  union block *header;  size_t size;  char *p;  size = xhdr->size;  header = start_private_header (name, size);  header->header.typeflag = type;  simple_finish_header (header);  p = xhdr->buffer;  do    {      size_t len;      header = find_next_block ();      len = BLOCKSIZE;      if (len > size)	len = size;      memcpy (header->buffer, p, len);      if (len < BLOCKSIZE)	memset (header->buffer + len, 0, BLOCKSIZE - len);      p += len;      size -= len;      set_next_block_after (header);    }  while (size > 0);  xheader_destroy (xhdr);  if (type == XGLTYPE)    global_header_count++;}voidxheader_write_global (struct xheader *xhdr){  char *name;  struct keyword_list *kp;  if (!keyword_global_override_list)    return;  xheader_init (xhdr);  for (kp = keyword_global_override_list; kp; kp = kp->next)    code_string (kp->value, kp->pattern, xhdr);  xheader_finish (xhdr);  xheader_write (XGLTYPE, name = xheader_ghdr_name (), xhdr);  free (name);}/* General Interface */struct xhdr_tab{  char const *keyword;  void (*coder) (struct tar_stat_info const *, char const *,		 struct xheader *, void const *data);  void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);  bool protect;};/* This declaration must be extern, because ISO C99 section 6.9.2   prohibits a tentative definition that has both internal linkage and   incomplete type.  If we made it static, we'd have to declare its   size which would be a maintenance pain; if we put its initializer   here, we'd need a boatload of forward declarations, which would be   even more of a pain.  */extern struct xhdr_tab const xhdr_tab[];static struct xhdr_tab const *locate_handler (char const *keyword){  struct xhdr_tab const *p;  for (p = xhdr_tab; p->keyword; p++)    if (strcmp (p->keyword, keyword) == 0)      return p;  return NULL;}static boolxheader_protected_pattern_p (const char *pattern){  struct xhdr_tab const *p;  for (p = xhdr_tab; p->keyword; p++)    if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)      return true;  return false;}static boolxheader_protected_keyword_p (const char *keyword){  struct xhdr_tab const *p;  for (p = xhdr_tab; p->keyword; p++)    if (p->protect && strcmp (p->keyword, keyword) == 0)      return true;  return false;}/* Decode a single extended header record, advancing *PTR to the next record.   Return true on success, false otherwise.  */static booldecode_record (struct xheader *xhdr,	       char **ptr,	       void (*handler) (void *, char const *, char const *, size_t),	       void *data){  char *start = *ptr;  char *p = start;  uintmax_t u;  size_t len;  char *len_lim;  char const *keyword;  char *nextp;  size_t len_max = xhdr->buffer + xhdr->size - start;  while (*p == ' ' || *p == '\t')    p++;  if (! ISDIGIT (*p))    {      if (*p)	ERROR ((0, 0, _("Malformed extended header: missing length")));      return false;    }  errno = 0;  len = u = strtoumax (p, &len_lim, 10);  if (len != u || errno == ERANGE)    {      ERROR ((0, 0, _("Extended header length is out of allowed range")));

⌨️ 快捷键说明

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