Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/data_extract_all.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1122 by niro, Sun May 30 11:32:42 2010 UTC revision 1123 by niro, Wed Aug 18 21:56:57 2010 UTC
# Line 12  void FAST_FUNC data_extract_all(archive_ Line 12  void FAST_FUNC data_extract_all(archive_
12   int dst_fd;   int dst_fd;
13   int res;   int res;
14    
15    #if ENABLE_FEATURE_TAR_SELINUX
16     char *sctx = archive_handle->tar__next_file_sctx;
17     if (!sctx)
18     sctx = archive_handle->tar__global_sctx;
19     if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
20     setfscreatecon(sctx);
21     free(archive_handle->tar__next_file_sctx);
22     archive_handle->tar__next_file_sctx = NULL;
23     }
24    #endif
25    
26   if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {   if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
27   char *slash = strrchr(file_header->name, '/');   char *slash = strrchr(file_header->name, '/');
28   if (slash) {   if (slash) {
# Line 23  void FAST_FUNC data_extract_all(archive_ Line 34  void FAST_FUNC data_extract_all(archive_
34    
35   if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {   if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
36   /* Remove the entry if it exists */   /* Remove the entry if it exists */
37   if ((!S_ISDIR(file_header->mode))   if (!S_ISDIR(file_header->mode)) {
38   && (unlink(file_header->name) == -1)   /* Is it hardlink?
39   && (errno != ENOENT)   * We encode hard links as regular files of size 0 with a symlink */
40   ) {   if (S_ISREG(file_header->mode)
41   bb_perror_msg_and_die("can't remove old file %s",   && file_header->link_target
42   file_header->name);   && file_header->size == 0
43     ) {
44     /* Ugly special case:
45     * tar cf t.tar hardlink1 hardlink2 hardlink1
46     * results in this tarball structure:
47     * hardlink1
48     * hardlink2 -> hardlink1
49     * hardlink1 -> hardlink1 <== !!!
50     */
51     if (strcmp(file_header->link_target, file_header->name) == 0)
52     goto ret;
53     }
54     /* Proceed with deleting */
55     if (unlink(file_header->name) == -1
56     && errno != ENOENT
57     ) {
58     bb_perror_msg_and_die("can't remove old file %s",
59     file_header->name);
60     }
61   }   }
62   }   }
63   else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {   else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
# Line 45  void FAST_FUNC data_extract_all(archive_ Line 74  void FAST_FUNC data_extract_all(archive_
74   "same age file exists", file_header->name);   "same age file exists", file_header->name);
75   }   }
76   data_skip(archive_handle);   data_skip(archive_handle);
77   return;   goto ret;
78   }   }
79   else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {   else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
80   bb_perror_msg_and_die("can't remove old file %s",   bb_perror_msg_and_die("can't remove old file %s",
# Line 54  void FAST_FUNC data_extract_all(archive_ Line 83  void FAST_FUNC data_extract_all(archive_
83   }   }
84    
85   /* Handle hard links separately   /* Handle hard links separately
86   * We identified hard links as regular files of size 0 with a symlink */   * We encode hard links as regular files of size 0 with a symlink */
87   if (S_ISREG(file_header->mode)   if (S_ISREG(file_header->mode)
88   && file_header->link_target   && file_header->link_target
89   && file_header->size == 0   && file_header->size == 0
# Line 67  void FAST_FUNC data_extract_all(archive_ Line 96  void FAST_FUNC data_extract_all(archive_
96   file_header->name,   file_header->name,
97   file_header->link_target);   file_header->link_target);
98   }   }
99   } else {   /* Hardlinks have no separate mode/ownership, skip chown/chmod */
100   /* Create the filesystem entry */   goto ret;
101   switch (file_header->mode & S_IFMT) {   }
102   case S_IFREG: {  
103   /* Regular file */   /* Create the filesystem entry */
104   int flags = O_WRONLY | O_CREAT | O_EXCL;   switch (file_header->mode & S_IFMT) {
105   if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)   case S_IFREG: {
106   flags = O_WRONLY | O_CREAT | O_TRUNC;   /* Regular file */
107   dst_fd = xopen3(file_header->name,   int flags = O_WRONLY | O_CREAT | O_EXCL;
108   flags,   if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
109   file_header->mode   flags = O_WRONLY | O_CREAT | O_TRUNC;
110   );   dst_fd = xopen3(file_header->name,
111   bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);   flags,
112   close(dst_fd);   file_header->mode
113   break;   );
114   }   bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
115   case S_IFDIR:   close(dst_fd);
116   res = mkdir(file_header->name, file_header->mode);   break;
117   if ((res == -1)   }
118   && (errno != EISDIR) /* btw, Linux doesn't return this */   case S_IFDIR:
119   && (errno != EEXIST)   res = mkdir(file_header->name, file_header->mode);
120   && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)   if ((res == -1)
121   ) {   && (errno != EISDIR) /* btw, Linux doesn't return this */
122   bb_perror_msg("can't make dir %s", file_header->name);   && (errno != EEXIST)
123   }   && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
124   break;   ) {
125   case S_IFLNK:   bb_perror_msg("can't make dir %s", file_header->name);
126   /* Symlink */   }
127   res = symlink(file_header->link_target, file_header->name);   break;
128   if ((res == -1)   case S_IFLNK:
129   && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)   /* Symlink */
130   ) {  //TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
131   bb_perror_msg("can't create %slink "   res = symlink(file_header->link_target, file_header->name);
132   "from %s to %s", "sym",   if ((res == -1)
133   file_header->name,   && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
134   file_header->link_target);   ) {
135   }   bb_perror_msg("can't create %slink "
136   break;   "from %s to %s", "sym",
137   case S_IFSOCK:   file_header->name,
138   case S_IFBLK:   file_header->link_target);
139   case S_IFCHR:   }
140   case S_IFIFO:   break;
141   res = mknod(file_header->name, file_header->mode, file_header->device);   case S_IFSOCK:
142   if ((res == -1)   case S_IFBLK:
143   && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)   case S_IFCHR:
144   ) {   case S_IFIFO:
145   bb_perror_msg("can't create node %s", file_header->name);   res = mknod(file_header->name, file_header->mode, file_header->device);
146   }   if ((res == -1)
147   break;   && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
148   default:   ) {
149   bb_error_msg_and_die("unrecognized file type");   bb_perror_msg("can't create node %s", file_header->name);
150   }   }
151     break;
152     default:
153     bb_error_msg_and_die("unrecognized file type");
154   }   }
155    
156   if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {   if (!S_ISLNK(file_header->mode)) {
157  #if ENABLE_FEATURE_TAR_UNAME_GNAME   if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
  if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {  
158   uid_t uid = file_header->uid;   uid_t uid = file_header->uid;
159   gid_t gid = file_header->gid;   gid_t gid = file_header->gid;
160    #if ENABLE_FEATURE_TAR_UNAME_GNAME
161   if (file_header->tar__uname) {   if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
162     if (file_header->tar__uname) {
163  //TODO: cache last name/id pair?  //TODO: cache last name/id pair?
164   struct passwd *pwd = getpwnam(file_header->tar__uname);   struct passwd *pwd = getpwnam(file_header->tar__uname);
165   if (pwd) uid = pwd->pw_uid;   if (pwd) uid = pwd->pw_uid;
166   }   }
167   if (file_header->tar__gname) {   if (file_header->tar__gname) {
168   struct group *grp = getgrnam(file_header->tar__gname);   struct group *grp = getgrnam(file_header->tar__gname);
169   if (grp) gid = grp->gr_gid;   if (grp) gid = grp->gr_gid;
170     }
171   }   }
172    #endif
173   /* GNU tar 1.15.1 uses chown, not lchown */   /* GNU tar 1.15.1 uses chown, not lchown */
174   chown(file_header->name, uid, gid);   chown(file_header->name, uid, gid);
175   } else   }
 #endif  
  chown(file_header->name, file_header->uid, file_header->gid);  
  }  
  if (!S_ISLNK(file_header->mode)) {  
176   /* uclibc has no lchmod, glibc is even stranger -   /* uclibc has no lchmod, glibc is even stranger -
177   * it has lchmod which seems to do nothing!   * it has lchmod which seems to do nothing!
178   * so we use chmod... */   * so we use chmod... */
179   if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {   if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
180   chmod(file_header->name, file_header->mode);   chmod(file_header->name, file_header->mode);
181   }   }
  /* same for utime */  
182   if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {   if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
183   struct timeval t[2];   struct timeval t[2];
184    
# Line 158  void FAST_FUNC data_extract_all(archive_ Line 187  void FAST_FUNC data_extract_all(archive_
187   utimes(file_header->name, t);   utimes(file_header->name, t);
188   }   }
189   }   }
190    
191     ret: ;
192    #if ENABLE_FEATURE_TAR_SELINUX
193     if (sctx) {
194     /* reset the context after creating an entry */
195     setfscreatecon(NULL);
196     }
197    #endif
198  }  }

Legend:
Removed from v.1122  
changed lines
  Added in v.1123