Magellan Linux

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

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

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 7  Line 7 
7  #include "libbb.h"  #include "libbb.h"
8  #include "unarchive.h"  #include "unarchive.h"
9    
10  typedef struct hardlinks_s {  typedef struct hardlinks_t {
11   char *name;   struct hardlinks_t *next;
12   int inode;   int inode; /* TODO: must match maj/min too! */
13   struct hardlinks_s *next;   int mode ;
14     int mtime; /* These three are useful only in corner case */
15     int uid  ; /* of hardlinks with zero size body */
16     int gid  ;
17     char name[1];
18  } hardlinks_t;  } hardlinks_t;
19    
20  char get_header_cpio(archive_handle_t *archive_handle)  char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
21  {  {
  static hardlinks_t *saved_hardlinks = NULL;  
  static unsigned short pending_hardlinks = 0;  
  static int inode;  
22   file_header_t *file_header = archive_handle->file_header;   file_header_t *file_header = archive_handle->file_header;
23   char cpio_header[110];   char cpio_header[110];
24   int namesize;   int namesize;
25   char dummy[16];   int major, minor, nlink, mode, inode;
26   int major, minor, nlink;   unsigned size, uid, gid, mtime;
27    
28   if (pending_hardlinks) { /* Deal with any pending hardlinks */  #define hardlinks_to_create (*(hardlinks_t **)(&archive_handle->ah_priv[0]))
29   hardlinks_t *tmp, *oldtmp;  #define created_hardlinks   (*(hardlinks_t **)(&archive_handle->ah_priv[1]))
30    #define block_count         (archive_handle->ah_priv[2])
31   tmp = saved_hardlinks;  // if (!archive_handle->ah_priv_inited) {
32   oldtmp = NULL;  // archive_handle->ah_priv_inited = 1;
33    // hardlinks_to_create = NULL;
34   file_header->link_name = file_header->name;  // created_hardlinks = NULL;
35   file_header->size = 0;  // }
   
  while (tmp) {  
  if (tmp->inode != inode) {  
  tmp = tmp->next;  
  continue;  
  }  
   
  file_header->name = tmp->name;  
   
  if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {  
  archive_handle->action_data(archive_handle);  
  archive_handle->action_header(archive_handle->file_header);  
  }  
   
  pending_hardlinks--;  
   
  oldtmp = tmp;  
  tmp = tmp->next;  
  free(oldtmp->name);  
  free(oldtmp);  
  if (oldtmp == saved_hardlinks)  
  saved_hardlinks = tmp;  
  }  
   
  file_header->name = file_header->link_name;  
   
  if (pending_hardlinks > 1) {  
  bb_error_msg("error resolving hardlink: archive made by GNU cpio 2.0-2.2?");  
  }  
   
  /* No more pending hardlinks, read next file entry */  
  pending_hardlinks = 0;  
  }  
36    
37   /* There can be padding before archive header */   /* There can be padding before archive header */
38   data_align(archive_handle, 4);   data_align(archive_handle, 4);
39    
40   if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) {   size = full_read(archive_handle->src_fd, cpio_header, 110);
41   return EXIT_FAILURE;   if (size == 0) {
42     goto create_hardlinks;
43     }
44     if (size != 110) {
45     bb_error_msg_and_die("short read");
46   }   }
47   archive_handle->offset += 110;   archive_handle->offset += 110;
48    
# Line 80  char get_header_cpio(archive_handle_t *a Line 52  char get_header_cpio(archive_handle_t *a
52   bb_error_msg_and_die("unsupported cpio format, use newc or crc");   bb_error_msg_and_die("unsupported cpio format, use newc or crc");
53   }   }
54    
55   {   if (sscanf(cpio_header + 6,
56   unsigned long tmpsize;   "%8x" "%8x" "%8x" "%8x"
57   sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",   "%8x" "%8x" "%8x" /*maj,min:*/ "%*16c"
58      dummy, &inode, (unsigned int*)&file_header->mode,   /*rmaj,rmin:*/"%8x" "%8x" "%8x" /*chksum: "%*8c"*/,
59      (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,   &inode, &mode, &uid, &gid,
60      &nlink, &file_header->mtime, &tmpsize,   &nlink, &mtime, &size,
61      dummy, &major, &minor, &namesize, dummy);   &major, &minor, &namesize) != 10)
62   file_header->size = tmpsize;   bb_error_msg_and_die("damaged cpio file");
63   }   file_header->mode = mode;
64     file_header->uid = uid;
65     file_header->gid = gid;
66     file_header->mtime = mtime;
67     file_header->size = size;
68    
69   free(file_header->name);   namesize &= 0x1fff; /* paranoia: limit names to 8k chars */
70   file_header->name = xzalloc(namesize + 1);   file_header->name = xzalloc(namesize + 1);
71   /* Read in filename */   /* Read in filename */
72   xread(archive_handle->src_fd, file_header->name, namesize);   xread(archive_handle->src_fd, file_header->name, namesize);
# Line 100  char get_header_cpio(archive_handle_t *a Line 76  char get_header_cpio(archive_handle_t *a
76   data_align(archive_handle, 4);   data_align(archive_handle, 4);
77    
78   if (strcmp(file_header->name, "TRAILER!!!") == 0) {   if (strcmp(file_header->name, "TRAILER!!!") == 0) {
79   /* Always round up */   /* Always round up. ">> 9" divides by 512 */
80   printf("%d blocks\n", (int) (archive_handle->offset % 512 ?   block_count = (void*)(ptrdiff_t) ((archive_handle->offset + 511) >> 9);
81                               archive_handle->offset / 512 + 1 :   goto create_hardlinks;
                              archive_handle->offset / 512  
                             ));  
  if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */  
  hardlinks_t *tmp = saved_hardlinks;  
  hardlinks_t *oldtmp = NULL;  
  while (tmp) {  
  bb_error_msg("%s not created: cannot resolve hardlink", tmp->name);  
  oldtmp = tmp;  
  tmp = tmp->next;  
  free(oldtmp->name);  
  free(oldtmp);  
  }  
  saved_hardlinks = NULL;  
  pending_hardlinks = 0;  
  }  
  return EXIT_FAILURE;  
82   }   }
83    
84     file_header->link_target = NULL;
85   if (S_ISLNK(file_header->mode)) {   if (S_ISLNK(file_header->mode)) {
86   file_header->link_name = xzalloc(file_header->size + 1);   file_header->size &= 0x1fff; /* paranoia: limit names to 8k chars */
87   xread(archive_handle->src_fd, file_header->link_name, file_header->size);   file_header->link_target = xzalloc(file_header->size + 1);
88     xread(archive_handle->src_fd, file_header->link_target, file_header->size);
89   archive_handle->offset += file_header->size;   archive_handle->offset += file_header->size;
90   file_header->size = 0; /* Stop possible seeks in future */   file_header->size = 0; /* Stop possible seeks in future */
  } else {  
  file_header->link_name = NULL;  
91   }   }
92   if (nlink > 1 && !S_ISDIR(file_header->mode)) {  
93   if (file_header->size == 0) { /* Put file on a linked list for later */  // TODO: data_extract_all can't deal with hardlinks to non-files...
94   hardlinks_t *new = xmalloc(sizeof(hardlinks_t));  // when fixed, change S_ISREG to !S_ISDIR here
95   new->next = saved_hardlinks;  
96   new->inode = inode;   if (nlink > 1 && S_ISREG(file_header->mode)) {
97   /* name current allocated, freed later */   hardlinks_t *new = xmalloc(sizeof(*new) + namesize);
98   new->name = file_header->name;   new->inode = inode;
99   file_header->name = NULL;   new->mode  = mode ;
100   saved_hardlinks = new;   new->mtime = mtime;
101     new->uid   = uid  ;
102     new->gid   = gid  ;
103     strcpy(new->name, file_header->name);
104     /* Put file on a linked list for later */
105     if (size == 0) {
106     new->next = hardlinks_to_create;
107     hardlinks_to_create = new;
108   return EXIT_SUCCESS; /* Skip this one */   return EXIT_SUCCESS; /* Skip this one */
109     /* TODO: this breaks cpio -t (it does not show hardlinks) */
110   }   }
111   /* Found the file with data in */   new->next = created_hardlinks;
112   pending_hardlinks = nlink;   created_hardlinks = new;
113   }   }
114   file_header->device = makedev(major, minor);   file_header->device = makedev(major, minor);
115    
116   if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {   if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
117   archive_handle->action_data(archive_handle);   archive_handle->action_data(archive_handle);
118   archive_handle->action_header(archive_handle->file_header);   archive_handle->action_header(file_header);
119   } else {   } else {
120   data_skip(archive_handle);   data_skip(archive_handle);
121   }   }
122    
123   archive_handle->offset += file_header->size;   archive_handle->offset += file_header->size;
124    
125   free(file_header->link_name);   free(file_header->link_target);
126     free(file_header->name);
127     file_header->link_target = NULL;
128     file_header->name = NULL;
129    
130   return EXIT_SUCCESS;   return EXIT_SUCCESS;
131    
132     create_hardlinks:
133     free(file_header->link_target);
134     free(file_header->name);
135    
136     while (hardlinks_to_create) {
137     hardlinks_t *cur;
138     hardlinks_t *make_me = hardlinks_to_create;
139    
140     hardlinks_to_create = make_me->next;
141    
142     memset(file_header, 0, sizeof(*file_header));
143     file_header->mtime = make_me->mtime;
144     file_header->name = make_me->name;
145     file_header->mode = make_me->mode;
146     file_header->uid = make_me->uid;
147     file_header->gid = make_me->gid;
148     /*file_header->size = 0;*/
149     /*file_header->link_target = NULL;*/
150    
151     /* Try to find a file we are hardlinked to */
152     cur = created_hardlinks;
153     while (cur) {
154     /* TODO: must match maj/min too! */
155     if (cur->inode == make_me->inode) {
156     file_header->link_target = cur->name;
157     /* link_target != NULL, size = 0: "I am a hardlink" */
158     if (archive_handle->filter(archive_handle) == EXIT_SUCCESS)
159     archive_handle->action_data(archive_handle);
160     free(make_me);
161     goto next_link;
162     }
163     cur = cur->next;
164     }
165     /* Oops... no file with such inode was created... do it now
166     * (happens when hardlinked files are empty (zero length)) */
167     if (archive_handle->filter(archive_handle) == EXIT_SUCCESS)
168     archive_handle->action_data(archive_handle);
169     /* Move to the list of created hardlinked files */
170     make_me->next = created_hardlinks;
171     created_hardlinks = make_me;
172     next_link: ;
173     }
174    
175     while (created_hardlinks) {
176     hardlinks_t *p = created_hardlinks;
177     created_hardlinks = p->next;
178     free(p);
179     }
180    
181     return EXIT_FAILURE; /* "No more files to process" */
182  }  }

Legend:
Removed from v.815  
changed lines
  Added in v.816