43 |
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) |
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) |
44 |
# endif |
# endif |
45 |
|
|
|
# ifndef FILE_SYSTEM_PREFIX_LEN |
|
|
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 |
|
|
# endif |
|
|
|
|
|
#ifndef SYMLINK_USES_UMASK |
|
|
# define UMASKED_SYMLINK(name1,name2,mode) symlink(name1,name2) |
|
|
#else |
|
|
# define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode) |
|
|
#endif /* SYMLINK_USES_UMASK */ |
|
|
|
|
46 |
/* Return 1 if an array of N objects, each of size S, cannot exist due |
/* Return 1 if an array of N objects, each of size S, cannot exist due |
47 |
to size arithmetic overflow. S must be positive and N must be |
to size arithmetic overflow. S must be positive and N must be |
48 |
nonnegative. This is a macro, not an inline function, so that it |
nonnegative. This is a macro, not an inline function, so that it |
82 |
|
|
83 |
struct new_cpio_header { |
struct new_cpio_header { |
84 |
unsigned short c_magic; |
unsigned short c_magic; |
85 |
unsigned long c_ino; |
union { |
86 |
unsigned long c_mode; |
struct { |
87 |
unsigned long c_uid; |
unsigned long c_ino; |
88 |
unsigned long c_gid; |
unsigned long c_mode; |
89 |
unsigned long c_nlink; |
unsigned long c_uid; |
90 |
unsigned long c_mtime; |
unsigned long c_gid; |
91 |
unsigned long c_filesize; |
unsigned long c_nlink; |
92 |
long c_dev_maj; |
unsigned long c_mtime; |
93 |
long c_dev_min; |
unsigned long c_filesize; |
94 |
long c_rdev_maj; |
long c_dev_maj; |
95 |
long c_rdev_min; |
long c_dev_min; |
96 |
unsigned long c_namesize; |
long c_rdev_maj; |
97 |
unsigned long c_chksum; |
long c_rdev_min; |
98 |
|
unsigned long c_namesize; |
99 |
|
unsigned long c_chksum; |
100 |
|
}; |
101 |
|
unsigned long c_hdr[13]; |
102 |
|
}; |
103 |
char *c_name; |
char *c_name; |
104 |
char *c_tar_linkname; |
char *c_tar_linkname; |
105 |
}; |
}; |
106 |
|
|
107 |
/* Total number of bytes read and written for all files. |
/* Total number of bytes read and written for all files. |
108 |
Now that many tape drives hold more than 4Gb we need more than 32 |
* Now that many tape drives hold more than 4Gb we need more than 32 |
109 |
bits to hold input_bytes and output_bytes. But it's not worth |
* bits to hold input_bytes and output_bytes. |
110 |
the trouble of adding special multi-precision arithmetic if the |
*/ |
|
compiler doesn't support 64 bit ints since input_bytes and |
|
|
output_bytes are only used to print the number of blocks copied. */ |
|
|
#ifdef __GNUC__ |
|
111 |
long long input_bytes, output_bytes; |
long long input_bytes, output_bytes; |
|
#else |
|
|
long input_bytes, output_bytes; |
|
|
#endif |
|
112 |
|
|
113 |
/* Allocate N bytes of memory dynamically, with error checking. */ |
/* Allocate N bytes of memory dynamically, with error checking. */ |
114 |
|
|
115 |
void *xmalloc(size_t n) |
static void *xmalloc(size_t n) |
116 |
{ |
{ |
117 |
void *p; |
void *p; |
118 |
if (xalloc_oversized(n, 1) || (!(p = malloc(n)) && n != 0)) { |
if (xalloc_oversized(n, 1) || (!(p = malloc(n)) && n != 0)) { |
123 |
/* return xnmalloc_inline (n, 1); */ |
/* return xnmalloc_inline (n, 1); */ |
124 |
} |
} |
125 |
|
|
|
/* Change the size of an allocated block of memory P to N bytes, |
|
|
with error checking. */ |
|
|
|
|
|
void *xrealloc(void *p, size_t n) |
|
|
{ |
|
|
if (xalloc_oversized(n, 1) || (!(p = realloc(p, n)) && n != 0)) { |
|
|
fprintf(stderr, "%s: memory exhausted\n", progname); |
|
|
exit(1); |
|
|
} |
|
|
return p; |
|
|
/* return xnrealloc_inline (p, n, 1); */ |
|
|
} |
|
|
|
|
126 |
/* Clone STRING. */ |
/* Clone STRING. */ |
127 |
|
|
128 |
char *xstrdup(char const *string) |
static char *xstrdup(char const *string) |
129 |
{ |
{ |
130 |
size_t s = strlen(string) + 1; |
size_t s = strlen(string) + 1; |
131 |
return memcpy(xmalloc(s), string, s); |
return memcpy(xmalloc(s), string, s); |
163 |
must always be a multiple of 4 helps us (and our callers) |
must always be a multiple of 4 helps us (and our callers) |
164 |
insure this. */ |
insure this. */ |
165 |
|
|
166 |
void disk_empty_output_buffer(int out_des) |
static void disk_empty_output_buffer(int out_des) |
167 |
{ |
{ |
168 |
int bytes_written; |
int bytes_written; |
169 |
|
|
182 |
/* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full. |
/* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full. |
183 |
When `out_buff' fills up, flush it to file descriptor OUT_DES. */ |
When `out_buff' fills up, flush it to file descriptor OUT_DES. */ |
184 |
|
|
185 |
void disk_buffered_write(char *in_buf, int out_des, long num_bytes) |
static void disk_buffered_write(char *in_buf, int out_des, long num_bytes) |
186 |
{ |
{ |
187 |
register long bytes_left = num_bytes; /* Bytes needing to be copied. */ |
register long bytes_left = num_bytes; /* Bytes needing to be copied. */ |
188 |
register long space_left; /* Room left in output buffer. */ |
register long space_left; /* Room left in output buffer. */ |
211 |
OUT_DES is the file descriptor for output; |
OUT_DES is the file descriptor for output; |
212 |
NUM_BYTES is the number of bytes to copy. */ |
NUM_BYTES is the number of bytes to copy. */ |
213 |
|
|
214 |
void copy_files_tape_to_disk(int in_des, int out_des, long num_bytes) |
static void copy_files_tape_to_disk(int in_des, int out_des, long num_bytes) |
215 |
{ |
{ |
216 |
long size; |
long size; |
217 |
|
|
227 |
} |
} |
228 |
|
|
229 |
/* if IN_BUF is NULL, Skip the next NUM_BYTES bytes of file descriptor IN_DES. */ |
/* if IN_BUF is NULL, Skip the next NUM_BYTES bytes of file descriptor IN_DES. */ |
230 |
void tape_buffered_read(char *in_buf, int in_des, long num_bytes) |
static void tape_buffered_read(char *in_buf, int in_des, long num_bytes) |
231 |
{ |
{ |
232 |
register long bytes_left = num_bytes; /* Bytes needing to be copied. */ |
register long bytes_left = num_bytes; /* Bytes needing to be copied. */ |
233 |
register long space_left; /* Bytes to copy from input buffer. */ |
register long space_left; /* Bytes to copy from input buffer. */ |
258 |
struct new_cpio_header header; |
struct new_cpio_header header; |
259 |
}; |
}; |
260 |
|
|
261 |
struct deferment *create_deferment(struct new_cpio_header *file_hdr) |
static struct deferment *create_deferment(struct new_cpio_header *file_hdr) |
262 |
{ |
{ |
263 |
struct deferment *d; |
struct deferment *d; |
264 |
d = (struct deferment *)xmalloc(sizeof(struct deferment)); |
d = (struct deferment *)xmalloc(sizeof(struct deferment)); |
268 |
return d; |
return d; |
269 |
} |
} |
270 |
|
|
271 |
void free_deferment(struct deferment *d) |
static void free_deferment(struct deferment *d) |
272 |
{ |
{ |
273 |
free(d->header.c_name); |
free(d->header.c_name); |
274 |
free(d); |
free(d); |
275 |
} |
} |
276 |
|
|
277 |
int link_to_name(char *link_name, char *link_target) |
static int link_to_name(char *link_name, char *link_target) |
278 |
{ |
{ |
279 |
int res = link(link_target, link_name); |
int res = link(link_target, link_name); |
280 |
return res; |
return res; |
328 |
|
|
329 |
/* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */ |
/* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */ |
330 |
|
|
331 |
void |
static void |
332 |
add_inode(unsigned long node_num, char *file_name, unsigned long major_num, |
add_inode(unsigned long node_num, char *file_name, unsigned long major_num, |
333 |
unsigned long minor_num) |
unsigned long minor_num) |
334 |
{ |
{ |
375 |
hash_num++; |
hash_num++; |
376 |
} |
} |
377 |
|
|
378 |
char *find_inode_file(unsigned long node_num, unsigned long major_num, |
static char *find_inode_file(unsigned long node_num, unsigned long major_num, |
379 |
unsigned long minor_num) |
unsigned long minor_num) |
380 |
{ |
{ |
381 |
int start; /* Initial hash location. */ |
int start; /* Initial hash location. */ |
415 |
numbers is found, try and create another link to it using |
numbers is found, try and create another link to it using |
416 |
link_to_name, and return 0 for success and -1 for failure. */ |
link_to_name, and return 0 for success and -1 for failure. */ |
417 |
|
|
418 |
int |
static int |
419 |
link_to_maj_min_ino(char *file_name, int st_dev_maj, int st_dev_min, int st_ino) |
link_to_maj_min_ino(char *file_name, int st_dev_maj, int st_dev_min, int st_ino) |
420 |
{ |
{ |
421 |
int link_res; |
int link_res; |
433 |
static void copyin_regular_file(struct new_cpio_header *file_hdr, |
static void copyin_regular_file(struct new_cpio_header *file_hdr, |
434 |
int in_file_des); |
int in_file_des); |
435 |
|
|
436 |
void warn_junk_bytes(long bytes_skipped) |
static void warn_junk_bytes(long bytes_skipped) |
437 |
{ |
{ |
438 |
fprintf(stderr, "%s: warning: skipped %ld byte(s) of junk\n", |
fprintf(stderr, "%s: warning: skipped %ld byte(s) of junk\n", |
439 |
progname, bytes_skipped); |
progname, bytes_skipped); |
554 |
we are done reading the whole archive. Write out all of these |
we are done reading the whole archive. Write out all of these |
555 |
empty links that are still on the deferments list. */ |
empty links that are still on the deferments list. */ |
556 |
|
|
557 |
static void create_final_defers() |
static void create_final_defers(void) |
558 |
{ |
{ |
559 |
struct deferment *d; |
struct deferment *d; |
560 |
int link_res; |
int link_res; |
696 |
NAME has no file name components because it is all slashes, return |
NAME has no file name components because it is all slashes, return |
697 |
NAME if it is empty, the address of its last slash otherwise. */ |
NAME if it is empty, the address of its last slash otherwise. */ |
698 |
|
|
699 |
char *base_name(char const *name) |
static char *base_name(char const *name) |
700 |
{ |
{ |
701 |
char const *base = name + FILE_SYSTEM_PREFIX_LEN(name); |
char const *base = name; |
702 |
char const *p; |
char const *p; |
703 |
|
|
704 |
for (p = base; *p; p++) { |
for (p = base; *p; p++) { |
728 |
value returned by base_name. Act like strlen (NAME), except omit |
value returned by base_name. Act like strlen (NAME), except omit |
729 |
redundant trailing slashes. */ |
redundant trailing slashes. */ |
730 |
|
|
731 |
size_t base_len(char const *name) |
static size_t base_len(char const *name) |
732 |
{ |
{ |
733 |
size_t len; |
size_t len; |
734 |
|
|
745 |
the Unix rename and rmdir system calls return an "Invalid argument" error |
the Unix rename and rmdir system calls return an "Invalid argument" error |
746 |
when given a path that ends in "/" (except for the root directory). */ |
when given a path that ends in "/" (except for the root directory). */ |
747 |
|
|
748 |
bool strip_trailing_slashes(char *path) |
static bool strip_trailing_slashes(char *path) |
749 |
{ |
{ |
750 |
char *base = base_name(path); |
char *base = base_name(path); |
751 |
char *base_lim = base + base_len(base); |
char *base_lim = base + base_len(base); |
845 |
tape_buffered_read(link_name, in_file_des, file_hdr->c_filesize); |
tape_buffered_read(link_name, in_file_des, file_hdr->c_filesize); |
846 |
tape_skip_padding(in_file_des, file_hdr->c_filesize); |
tape_skip_padding(in_file_des, file_hdr->c_filesize); |
847 |
|
|
848 |
res = UMASKED_SYMLINK(link_name, file_hdr->c_name, file_hdr->c_mode); |
res = symlink(link_name, file_hdr->c_name); |
849 |
if (res < 0) { |
if (res < 0) { |
850 |
fprintf(stderr, "%s: UMASKED_SYMLINK %s: %s\n", |
fprintf(stderr, "%s: symlink %s: %s\n", |
851 |
progname, file_hdr->c_name, strerror(errno)); |
progname, file_hdr->c_name, strerror(errno)); |
852 |
free(link_name); |
free(link_name); |
853 |
return; |
return; |
879 |
|
|
880 |
case S_IFCHR: |
case S_IFCHR: |
881 |
case S_IFBLK: |
case S_IFBLK: |
|
#ifdef S_IFSOCK |
|
882 |
case S_IFSOCK: |
case S_IFSOCK: |
|
#endif |
|
|
#ifdef S_IFIFO |
|
883 |
case S_IFIFO: |
case S_IFIFO: |
|
#endif |
|
884 |
copyin_device(file_hdr); |
copyin_device(file_hdr); |
885 |
break; |
break; |
886 |
|
|
|
#ifdef S_IFLNK |
|
887 |
case S_IFLNK: |
case S_IFLNK: |
888 |
copyin_link(file_hdr, in_file_des); |
copyin_link(file_hdr, in_file_des); |
889 |
break; |
break; |
|
#endif |
|
890 |
|
|
891 |
default: |
default: |
892 |
fprintf(stderr, "%s: %s: unknown file type\n", |
fprintf(stderr, "%s: %s: unknown file type\n", |
900 |
file descriptor IN_DES, except for the magic number, which is |
file descriptor IN_DES, except for the magic number, which is |
901 |
already filled in. */ |
already filled in. */ |
902 |
|
|
903 |
void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des) |
static void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des) |
904 |
{ |
{ |
905 |
char ascii_header[112]; |
char ascii_header[13*8], *ah, hexbuf[9]; |
906 |
|
int i; |
907 |
|
|
908 |
tape_buffered_read(ascii_header, in_des, 104L); |
tape_buffered_read(ascii_header, in_des, 13*8); |
909 |
ascii_header[104] = '\0'; |
ah = ascii_header; |
910 |
sscanf(ascii_header, |
hexbuf[8] = '\0'; |
911 |
"%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx", |
for (i = 0; i < 13; i++) { |
912 |
&file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid, |
memcpy(hexbuf, ah, 8); |
913 |
&file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime, |
file_hdr->c_hdr[i] = strtoul(hexbuf, NULL, 16); |
914 |
&file_hdr->c_filesize, &file_hdr->c_dev_maj, |
ah += 8; |
915 |
&file_hdr->c_dev_min, &file_hdr->c_rdev_maj, |
} |
|
&file_hdr->c_rdev_min, &file_hdr->c_namesize, |
|
|
&file_hdr->c_chksum); |
|
916 |
/* Read file name from input. */ |
/* Read file name from input. */ |
917 |
if (file_hdr->c_name != NULL) |
if (file_hdr->c_name != NULL) |
918 |
free(file_hdr->c_name); |
free(file_hdr->c_name); |
932 |
/* Read the header, including the name of the file, from file |
/* Read the header, including the name of the file, from file |
933 |
descriptor IN_DES into FILE_HDR. */ |
descriptor IN_DES into FILE_HDR. */ |
934 |
|
|
935 |
void read_in_header(struct new_cpio_header *file_hdr, int in_des) |
static void read_in_header(struct new_cpio_header *file_hdr, int in_des) |
936 |
{ |
{ |
937 |
long bytes_skipped = 0; /* Bytes of junk found before magic number. */ |
long bytes_skipped = 0; /* Bytes of junk found before magic number. */ |
938 |
|
|
960 |
/* Read the collection from standard input and create files |
/* Read the collection from standard input and create files |
961 |
in the file system. */ |
in the file system. */ |
962 |
|
|
963 |
void process_copy_in() |
static void process_copy_in(void) |
964 |
{ |
{ |
965 |
char done = false; /* True if trailer reached. */ |
char done = false; /* True if trailer reached. */ |
966 |
struct new_cpio_header file_hdr; /* Output header information. */ |
struct new_cpio_header file_hdr; /* Output header information. */ |
1002 |
initialize all variables associated with the input and output |
initialize all variables associated with the input and output |
1003 |
buffers. */ |
buffers. */ |
1004 |
|
|
1005 |
void initialize_buffers() |
static void initialize_buffers(void) |
1006 |
{ |
{ |
1007 |
int in_buf_size, out_buf_size; |
int in_buf_size, out_buf_size; |
1008 |
|
|