/ [cpio] / cpio / src / util.c
To checkout: cvs -d:pserver:anonymous@cvs.gnu.org.ua:/cvsmirror/cpio co cpio/src/util.c
Puszcza

Annotation of /cpio/src/util.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.31 - (hide annotations)
Sat Feb 9 10:31:53 2008 UTC (13 years, 11 months ago) by gray
Branch: MAIN
CVS Tags: HEAD
Changes since 1.30: +3 -3 lines
File MIME type: text/plain
* NEWS, configure.ac: Raise the patchlevel number.
* THANKS: Update

* doc/cpio.texi: Fix a typo.
* src/extern.h (warn_if_file_changed): Fix type of the 2nd
argument.
* src/tar.c (write_out_tar_header): Stylistic change.
* src/util.c (copy_files_disk_to_disk): Fix types of automatic
variables.
(warn_if_file_changed): Fix type of the 2nd argument.

Patches supplied by Ladislav Michnovic.

1 gray 1.1 /* util.c - Several utility routines for cpio.
2 gray 1.19 Copyright (C) 1990, 1991, 1992, 2001, 2004,
3 gray 1.26 2006, 2007 Free Software Foundation, Inc.
4 gray 1.1
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7 gray 1.26 the Free Software Foundation; either version 3, or (at your option)
8 gray 1.1 any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15 gray 1.11 You should have received a copy of the GNU General Public
16     License along with this program; if not, write to the Free
17     Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301 USA. */
19 gray 1.1
20 gray 1.4 #include <system.h>
21 gray 1.1
22     #include <stdio.h>
23     #include <sys/types.h>
24     #include <sys/stat.h>
25     #include "cpiohdr.h"
26     #include "dstring.h"
27     #include "extern.h"
28 gray 1.17 #include <paxlib.h>
29 gray 1.13 #include "filetypes.h"
30 gray 1.12 #include <safe-read.h>
31     #include <full-write.h>
32 gray 1.4 #include <rmt.h>
33 gray 1.14 #include <hash.h>
34 gray 1.16 #include <utimens.h>
35 gray 1.1
36 gray 1.29 #ifdef HAVE_SYS_IOCTL_H
37     # include <sys/ioctl.h>
38     #endif
39 gray 1.1
40     #ifdef HAVE_SYS_MTIO_H
41 gray 1.12 # ifdef HAVE_SYS_IO_TRIOCTL_H
42     # include <sys/io/trioctl.h>
43     # endif
44     # include <sys/mtio.h>
45 gray 1.1 #endif
46    
47     #if !HAVE_DECL_ERRNO
48     extern int errno;
49     #endif
50    
51     /* Write `output_size' bytes of `output_buffer' to file
52     descriptor OUT_DES and reset `output_size' and `out_buff'. */
53    
54     void
55 gray 1.4 tape_empty_output_buffer (int out_des)
56 gray 1.1 {
57     int bytes_written;
58    
59     #ifdef BROKEN_LONG_TAPE_DRIVER
60     static long output_bytes_before_lseek = 0;
61    
62     /* Some tape drivers seem to have a signed internal seek pointer and
63     they lose if it overflows and becomes negative (e.g. when writing
64     tapes > 2Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
65     seek pointer and prevent it from overflowing. */
66     if (output_is_special
67     && ( (output_bytes_before_lseek += output_size) >= 1073741824L) )
68     {
69     lseek(out_des, 0L, SEEK_SET);
70     output_bytes_before_lseek = 0;
71     }
72     #endif
73    
74     bytes_written = rmtwrite (out_des, output_buffer, output_size);
75     if (bytes_written != output_size)
76     {
77     int rest_bytes_written;
78     int rest_output_size;
79    
80     if (output_is_special
81     && (bytes_written >= 0
82     || (bytes_written < 0
83     && (errno == ENOSPC || errno == EIO || errno == ENXIO))))
84     {
85     get_next_reel (out_des);
86     if (bytes_written > 0)
87     rest_output_size = output_size - bytes_written;
88     else
89     rest_output_size = output_size;
90     rest_bytes_written = rmtwrite (out_des, output_buffer,
91     rest_output_size);
92     if (rest_bytes_written != rest_output_size)
93     error (1, errno, _("write error"));
94     }
95     else
96     error (1, errno, _("write error"));
97     }
98     output_bytes += output_size;
99     out_buff = output_buffer;
100     output_size = 0;
101     }
102    
103 gray 1.22 static int sparse_write (int fildes, char *buf, unsigned int nbyte);
104    
105 gray 1.1 /* Write `output_size' bytes of `output_buffer' to file
106     descriptor OUT_DES and reset `output_size' and `out_buff'.
107     If `swapping_halfwords' or `swapping_bytes' is set,
108     do the appropriate swapping first. Our callers have
109     to make sure to only set these flags if `output_size'
110     is appropriate (a multiple of 4 for `swapping_halfwords',
111     2 for `swapping_bytes'). The fact that DISK_IO_BLOCK_SIZE
112     must always be a multiple of 4 helps us (and our callers)
113     insure this. */
114    
115     void
116 gray 1.4 disk_empty_output_buffer (int out_des)
117 gray 1.1 {
118     int bytes_written;
119    
120     if (swapping_halfwords || swapping_bytes)
121     {
122     if (swapping_halfwords)
123     {
124     int complete_words;
125     complete_words = output_size / 4;
126     swahw_array (output_buffer, complete_words);
127     if (swapping_bytes)
128     swab_array (output_buffer, 2 * complete_words);
129     }
130     else
131     {
132     int complete_halfwords;
133     complete_halfwords = output_size /2;
134     swab_array (output_buffer, complete_halfwords);
135     }
136     }
137    
138     if (sparse_flag)
139     bytes_written = sparse_write (out_des, output_buffer, output_size);
140     else
141     bytes_written = write (out_des, output_buffer, output_size);
142    
143     if (bytes_written != output_size)
144     {
145     error (1, errno, _("write error"));
146     }
147     output_bytes += output_size;
148     out_buff = output_buffer;
149     output_size = 0;
150     }
151    
152     /* Exchange the halfwords of each element of the array of COUNT longs
153     starting at PTR. PTR does not have to be aligned at a word
154     boundary. */
155    
156     void
157 gray 1.4 swahw_array (char *ptr, int count)
158 gray 1.1 {
159     char tmp;
160    
161     for (; count > 0; --count)
162     {
163     tmp = *ptr;
164     *ptr = *(ptr + 2);
165     *(ptr + 2) = tmp;
166     ++ptr;
167     tmp = *ptr;
168     *ptr = *(ptr + 2);
169     *(ptr + 2) = tmp;
170     ptr += 3;
171     }
172     }
173    
174     /* Read at most NUM_BYTES or `io_block_size' bytes, whichever is smaller,
175     into the start of `input_buffer' from file descriptor IN_DES.
176     Set `input_size' to the number of bytes read and reset `in_buff'.
177     Exit with an error if end of file is reached. */
178    
179     #ifdef BROKEN_LONG_TAPE_DRIVER
180     static long input_bytes_before_lseek = 0;
181     #endif
182    
183     static void
184 gray 1.4 tape_fill_input_buffer (int in_des, int num_bytes)
185 gray 1.1 {
186     #ifdef BROKEN_LONG_TAPE_DRIVER
187     /* Some tape drivers seem to have a signed internal seek pointer and
188     they lose if it overflows and becomes negative (e.g. when writing
189     tapes > 4Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
190     seek pointer and prevent it from overflowing. */
191     if (input_is_special
192     && ( (input_bytes_before_lseek += num_bytes) >= 1073741824L) )
193     {
194     lseek(in_des, 0L, SEEK_SET);
195     input_bytes_before_lseek = 0;
196     }
197     #endif
198     in_buff = input_buffer;
199     num_bytes = (num_bytes < io_block_size) ? num_bytes : io_block_size;
200     input_size = rmtread (in_des, input_buffer, num_bytes);
201     if (input_size == 0 && input_is_special)
202     {
203     get_next_reel (in_des);
204     input_size = rmtread (in_des, input_buffer, num_bytes);
205     }
206     if (input_size < 0)
207     error (1, errno, _("read error"));
208     if (input_size == 0)
209     {
210     error (0, 0, _("premature end of file"));
211     exit (1);
212     }
213     input_bytes += input_size;
214     }
215    
216     /* Read at most NUM_BYTES or `DISK_IO_BLOCK_SIZE' bytes, whichever is smaller,
217     into the start of `input_buffer' from file descriptor IN_DES.
218     Set `input_size' to the number of bytes read and reset `in_buff'.
219     Exit with an error if end of file is reached. */
220    
221     static int
222 gray 1.10 disk_fill_input_buffer (int in_des, off_t num_bytes)
223 gray 1.1 {
224     in_buff = input_buffer;
225     num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE;
226     input_size = read (in_des, input_buffer, num_bytes);
227     if (input_size < 0)
228     {
229     input_size = 0;
230     return (-1);
231     }
232     else if (input_size == 0)
233     return (1);
234     input_bytes += input_size;
235     return (0);
236     }
237    
238     /* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
239     When `out_buff' fills up, flush it to file descriptor OUT_DES. */
240    
241     void
242 gray 1.10 tape_buffered_write (char *in_buf, int out_des, off_t num_bytes)
243 gray 1.1 {
244 gray 1.10 off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
245     off_t space_left; /* Room left in output buffer. */
246 gray 1.1
247     while (bytes_left > 0)
248     {
249     space_left = io_block_size - output_size;
250     if (space_left == 0)
251     tape_empty_output_buffer (out_des);
252     else
253     {
254     if (bytes_left < space_left)
255     space_left = bytes_left;
256 gray 1.7 memcpy (out_buff, in_buf, (unsigned) space_left);
257 gray 1.1 out_buff += space_left;
258     output_size += space_left;
259     in_buf += space_left;
260     bytes_left -= space_left;
261     }
262     }
263     }
264    
265     /* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
266     When `out_buff' fills up, flush it to file descriptor OUT_DES. */
267    
268     void
269 gray 1.10 disk_buffered_write (char *in_buf, int out_des, off_t num_bytes)
270 gray 1.1 {
271 gray 1.10 off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
272     off_t space_left; /* Room left in output buffer. */
273 gray 1.1
274     while (bytes_left > 0)
275     {
276     space_left = DISK_IO_BLOCK_SIZE - output_size;
277     if (space_left == 0)
278     disk_empty_output_buffer (out_des);
279     else
280     {
281     if (bytes_left < space_left)
282     space_left = bytes_left;
283 gray 1.9 memcpy (out_buff, in_buf, (unsigned) space_left);
284 gray 1.1 out_buff += space_left;
285     output_size += space_left;
286     in_buf += space_left;
287     bytes_left -= space_left;
288     }
289     }
290     }
291    
292     /* Copy NUM_BYTES of buffer `in_buff' into IN_BUF.
293     `in_buff' may be partly full.
294     When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
295    
296     void
297 gray 1.10 tape_buffered_read (char *in_buf, int in_des, off_t num_bytes)
298 gray 1.1 {
299 gray 1.10 off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
300     off_t space_left; /* Bytes to copy from input buffer. */
301 gray 1.1
302     while (bytes_left > 0)
303     {
304     if (input_size == 0)
305     tape_fill_input_buffer (in_des, io_block_size);
306     if (bytes_left < input_size)
307     space_left = bytes_left;
308     else
309     space_left = input_size;
310 gray 1.7 memcpy (in_buf, in_buff, (unsigned) space_left);
311 gray 1.1 in_buff += space_left;
312     in_buf += space_left;
313     input_size -= space_left;
314     bytes_left -= space_left;
315     }
316     }
317    
318     /* Copy the the next NUM_BYTES bytes of `input_buffer' into PEEK_BUF.
319     If NUM_BYTES bytes are not available, read the next `io_block_size' bytes
320     into the end of `input_buffer' and update `input_size'.
321    
322     Return the number of bytes copied into PEEK_BUF.
323     If the number of bytes returned is less than NUM_BYTES,
324     then EOF has been reached. */
325    
326     int
327 gray 1.4 tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
328 gray 1.1 {
329     long tmp_input_size;
330     long got_bytes;
331     char *append_buf;
332    
333     #ifdef BROKEN_LONG_TAPE_DRIVER
334     /* Some tape drivers seem to have a signed internal seek pointer and
335     they lose if it overflows and becomes negative (e.g. when writing
336     tapes > 4Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
337     seek pointer and prevent it from overflowing. */
338     if (input_is_special
339     && ( (input_bytes_before_lseek += num_bytes) >= 1073741824L) )
340     {
341     lseek(in_des, 0L, SEEK_SET);
342     input_bytes_before_lseek = 0;
343     }
344     #endif
345    
346     while (input_size < num_bytes)
347     {
348     append_buf = in_buff + input_size;
349     if ( (append_buf - input_buffer) >= input_buffer_size)
350     {
351     /* We can keep up to 2 "blocks" (either the physical block size
352     or 512 bytes(the size of a tar record), which ever is
353     larger) in the input buffer when we are peeking. We
354     assume that our caller will never be interested in peeking
355     ahead at more than 512 bytes, so we know that by the time
356     we need a 3rd "block" in the buffer we can throw away the
357     first block to make room. */
358     int half;
359     half = input_buffer_size / 2;
360 gray 1.7 memmove (input_buffer, input_buffer + half, half);
361 gray 1.1 in_buff = in_buff - half;
362     append_buf = append_buf - half;
363     }
364     tmp_input_size = rmtread (in_des, append_buf, io_block_size);
365     if (tmp_input_size == 0)
366     {
367     if (input_is_special)
368     {
369     get_next_reel (in_des);
370     tmp_input_size = rmtread (in_des, append_buf, io_block_size);
371     }
372     else
373     break;
374     }
375     if (tmp_input_size < 0)
376     error (1, errno, _("read error"));
377     input_bytes += tmp_input_size;
378     input_size += tmp_input_size;
379     }
380     if (num_bytes <= input_size)
381     got_bytes = num_bytes;
382     else
383     got_bytes = input_size;
384 gray 1.7 memcpy (peek_buf, in_buff, (unsigned) got_bytes);
385 gray 1.1 return got_bytes;
386     }
387    
388     /* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
389    
390     void
391 gray 1.21 tape_toss_input (int in_des, off_t num_bytes)
392 gray 1.1 {
393 gray 1.21 off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
394     off_t space_left; /* Bytes to copy from input buffer. */
395 gray 1.1
396     while (bytes_left > 0)
397     {
398     if (input_size == 0)
399     tape_fill_input_buffer (in_des, io_block_size);
400     if (bytes_left < input_size)
401     space_left = bytes_left;
402     else
403     space_left = input_size;
404    
405     if (crc_i_flag && only_verify_crc_flag)
406     {
407     int k;
408     for (k = 0; k < space_left; ++k)
409     crc += in_buff[k] & 0xff;
410     }
411    
412     in_buff += space_left;
413     input_size -= space_left;
414     bytes_left -= space_left;
415     }
416     }
417    
418 gray 1.7 void
419 gray 1.10 write_nuls_to_file (off_t num_bytes, int out_des,
420     void (*writer) (char *in_buf, int out_des, off_t num_bytes))
421 gray 1.4 {
422 gray 1.10 off_t blocks;
423     off_t extra_bytes;
424     off_t i;
425 gray 1.7 static char zeros_512[512];
426    
427     blocks = num_bytes / sizeof zeros_512;
428     extra_bytes = num_bytes % sizeof zeros_512;
429 gray 1.5 for (i = 0; i < blocks; ++i)
430 gray 1.7 writer (zeros_512, out_des, sizeof zeros_512);
431 gray 1.5 if (extra_bytes)
432     writer (zeros_512, out_des, extra_bytes);
433 gray 1.4 }
434    
435 gray 1.1 /* Copy a file using the input and output buffers, which may start out
436     partly full. After the copy, the files are not closed nor the last
437     block flushed to output, and the input buffer may still be partly
438     full. If `crc_i_flag' is set, add each byte to `crc'.
439     IN_DES is the file descriptor for input;
440     OUT_DES is the file descriptor for output;
441     NUM_BYTES is the number of bytes to copy. */
442    
443     void
444 gray 1.10 copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes)
445 gray 1.1 {
446 gray 1.30 off_t size;
447     off_t k;
448 gray 1.1
449     while (num_bytes > 0)
450     {
451     if (input_size == 0)
452     tape_fill_input_buffer (in_des, io_block_size);
453     size = (input_size < num_bytes) ? input_size : num_bytes;
454     if (crc_i_flag)
455     {
456     for (k = 0; k < size; ++k)
457     crc += in_buff[k] & 0xff;
458     }
459     disk_buffered_write (in_buff, out_des, size);
460     num_bytes -= size;
461     input_size -= size;
462     in_buff += size;
463     }
464     }
465     /* Copy a file using the input and output buffers, which may start out
466     partly full. After the copy, the files are not closed nor the last
467     block flushed to output, and the input buffer may still be partly
468     full. If `crc_i_flag' is set, add each byte to `crc'.
469     IN_DES is the file descriptor for input;
470     OUT_DES is the file descriptor for output;
471     NUM_BYTES is the number of bytes to copy. */
472    
473     void
474 gray 1.10 copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes,
475 gray 1.4 char *filename)
476 gray 1.1 {
477 gray 1.30 off_t size;
478     off_t k;
479 gray 1.1 int rc;
480 gray 1.10 off_t original_num_bytes;
481 gray 1.1
482     original_num_bytes = num_bytes;
483    
484     while (num_bytes > 0)
485     {
486     if (input_size == 0)
487     if (rc = disk_fill_input_buffer (in_des,
488 gray 1.12 num_bytes < DISK_IO_BLOCK_SIZE ?
489     num_bytes : DISK_IO_BLOCK_SIZE))
490 gray 1.1 {
491     if (rc > 0)
492 gray 1.20 {
493     char buf[UINTMAX_STRSIZE_BOUND];
494     error (0, 0,
495     ngettext ("File %s shrunk by %s byte, padding with zeros",
496     "File %s shrunk by %s bytes, padding with zeros",
497     num_bytes),
498     filename, STRINGIFY_BIGINT (num_bytes, buf));
499     }
500 gray 1.1 else
501 gray 1.10 error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
502 gray 1.1 original_num_bytes - num_bytes, filename);
503 gray 1.5 write_nuls_to_file (num_bytes, out_des, tape_buffered_write);
504 gray 1.1 break;
505     }
506     size = (input_size < num_bytes) ? input_size : num_bytes;
507     if (crc_i_flag)
508     {
509     for (k = 0; k < size; ++k)
510     crc += in_buff[k] & 0xff;
511     }
512     tape_buffered_write (in_buff, out_des, size);
513     num_bytes -= size;
514     input_size -= size;
515     in_buff += size;
516     }
517     }
518     /* Copy a file using the input and output buffers, which may start out
519     partly full. After the copy, the files are not closed nor the last
520     block flushed to output, and the input buffer may still be partly
521     full. If `crc_i_flag' is set, add each byte to `crc'.
522     IN_DES is the file descriptor for input;
523     OUT_DES is the file descriptor for output;
524     NUM_BYTES is the number of bytes to copy. */
525    
526     void
527 gray 1.10 copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes,
528 gray 1.4 char *filename)
529 gray 1.1 {
530 gray 1.31 off_t size;
531     off_t k;
532 gray 1.10 off_t original_num_bytes;
533 gray 1.1 int rc;
534    
535     original_num_bytes = num_bytes;
536     while (num_bytes > 0)
537     {
538     if (input_size == 0)
539 gray 1.3 if (rc = disk_fill_input_buffer (in_des, num_bytes))
540 gray 1.1 {
541     if (rc > 0)
542 gray 1.20 {
543     char buf[UINTMAX_STRSIZE_BOUND];
544     error (0, 0,
545     ngettext ("File %s shrunk by %s byte, padding with zeros",
546     "File %s shrunk by %s bytes, padding with zeros",
547     num_bytes),
548     filename, STRINGIFY_BIGINT (num_bytes, buf));
549     }
550 gray 1.1 else
551 gray 1.10 error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
552 gray 1.1 original_num_bytes - num_bytes, filename);
553 gray 1.5 write_nuls_to_file (num_bytes, out_des, disk_buffered_write);
554 gray 1.1 break;
555     }
556     size = (input_size < num_bytes) ? input_size : num_bytes;
557     if (crc_i_flag)
558     {
559     for (k = 0; k < size; ++k)
560     crc += in_buff[k] & 0xff;
561     }
562     disk_buffered_write (in_buff, out_des, size);
563     num_bytes -= size;
564     input_size -= size;
565     in_buff += size;
566     }
567     }
568    
569     /* Warn if file changed while it was being copied. */
570    
571     void
572 gray 1.31 warn_if_file_changed (char *file_name, off_t old_file_size,
573 gray 1.30 time_t old_file_mtime)
574 gray 1.1 {
575     struct stat new_file_stat;
576     if ((*xstat) (file_name, &new_file_stat) < 0)
577     {
578 gray 1.12 stat_error (file_name);
579 gray 1.1 return;
580     }
581    
582     /* Only check growth, shrinkage detected in copy_files_disk_to_{disk,tape}()
583     */
584     if (new_file_stat.st_size > old_file_size)
585 gray 1.21 error (0, 0,
586     ngettext ("File %s grew, %"PRIuMAX" new byte not copied",
587     "File %s grew, %"PRIuMAX" new bytes not copied",
588     (long)(new_file_stat.st_size - old_file_size)),
589     file_name, (uintmax_t) (new_file_stat.st_size - old_file_size));
590 gray 1.1
591     else if (new_file_stat.st_mtime != old_file_mtime)
592     error (0, 0, _("File %s was modified while being copied"), file_name);
593     }
594    
595     /* Create all directories up to but not including the last part of NAME.
596     Do not destroy any nondirectories while creating directories. */
597    
598     void
599 gray 1.4 create_all_directories (char *name)
600 gray 1.1 {
601     char *dir;
602     int mode;
603     #ifdef HPUX_CDF
604     int cdf;
605     #endif
606    
607 gray 1.6 dir = dir_name (name);
608 gray 1.1 mode = 0700;
609     #ifdef HPUX_CDF
610     cdf = islastparentcdf (name);
611     if (cdf)
612     {
613     dir [strlen (dir) - 1] = '\0'; /* remove final + */
614     mode = 04700;
615     }
616    
617     #endif
618    
619     if (dir == NULL)
620     error (2, 0, _("virtual memory exhausted"));
621    
622     if (dir[0] != '.' || dir[1] != '\0')
623 gray 1.27 {
624     const char *fmt;
625     if (warn_option & CPIO_WARN_INTERDIR)
626     fmt = _("Creating intermediate directory `%s'");
627     else
628     fmt = NULL;
629 gray 1.28 make_path (dir, -1, -1, fmt);
630 gray 1.27 }
631 gray 1.1
632     free (dir);
633     }
634    
635     /* Prepare to append to an archive. We have been in
636     process_copy_in, keeping track of the position where
637     the last header started in `last_header_start'. Now we
638     have the starting position of the last header (the TRAILER!!!
639     header, or blank record for tar archives) and we want to start
640     writing (appending) over the last header. The last header may
641     be in the middle of a block, so to keep the buffering in sync
642     we lseek back to the start of the block, read everything up
643     to but not including the last header, lseek back to the start
644     of the block, and then do a copy_buf_out of what we read.
645     Actually, we probably don't have to worry so much about keeping the
646     buffering perfect since you can only append to archives that
647     are disk files. */
648    
649     void
650 gray 1.4 prepare_append (int out_file_des)
651 gray 1.1 {
652     int start_of_header;
653     int start_of_block;
654     int useful_bytes_in_block;
655     char *tmp_buf;
656    
657     start_of_header = last_header_start;
658     /* Figure out how many bytes we will rewrite, and where they start. */
659     useful_bytes_in_block = start_of_header % io_block_size;
660     start_of_block = start_of_header - useful_bytes_in_block;
661    
662     if (lseek (out_file_des, start_of_block, SEEK_SET) < 0)
663     error (1, errno, _("cannot seek on output"));
664     if (useful_bytes_in_block > 0)
665     {
666     tmp_buf = (char *) xmalloc (useful_bytes_in_block);
667     read (out_file_des, tmp_buf, useful_bytes_in_block);
668     if (lseek (out_file_des, start_of_block, SEEK_SET) < 0)
669     error (1, errno, _("cannot seek on output"));
670     /* fix juo -- is this copy_tape_buf_out? or copy_disk? */
671     tape_buffered_write (tmp_buf, out_file_des, useful_bytes_in_block);
672     free (tmp_buf);
673     }
674    
675     /* We are done reading the archive, so clear these since they
676     will now be used for reading in files that we are appending
677     to the archive. */
678     input_size = 0;
679     input_bytes = 0;
680     in_buff = input_buffer;
681     }
682    
683     /* Support for remembering inodes with multiple links. Used in the
684     "copy in" and "copy pass" modes for making links instead of copying
685     the file. */
686    
687     struct inode_val
688     {
689     unsigned long inode;
690     unsigned long major_num;
691     unsigned long minor_num;
692     char *file_name;
693     };
694    
695     /* Inode hash table. Allocated by first call to add_inode. */
696 gray 1.14 static Hash_table *hash_table = NULL;
697 gray 1.1
698 gray 1.14 static size_t
699     inode_val_hasher (const void *val, size_t n_buckets)
700     {
701     const struct inode_val *ival = val;
702     return ival->inode % n_buckets;
703     }
704 gray 1.1
705 gray 1.14 static bool
706     inode_val_compare (const void *val1, const void *val2)
707     {
708     const struct inode_val *ival1 = val1;
709     const struct inode_val *ival2 = val2;
710     return ival1->inode == ival2->inode
711     && ival1->major_num == ival2->major_num
712     && ival1->minor_num == ival2->minor_num;
713     }
714 gray 1.1
715     char *
716 gray 1.4 find_inode_file (unsigned long node_num, unsigned long major_num,
717     unsigned long minor_num)
718 gray 1.1 {
719 gray 1.14 struct inode_val sample;
720     struct inode_val *ival;
721    
722     if (!hash_table)
723     return NULL;
724    
725     sample.inode = node_num;
726     sample.major_num = major_num;
727     sample.minor_num = minor_num;
728     ival = hash_lookup (hash_table, &sample);
729     return ival ? ival->file_name : NULL;
730 gray 1.4 }
731    
732 gray 1.1 /* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */
733    
734     void
735 gray 1.4 add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
736     unsigned long minor_num)
737 gray 1.1 {
738     struct inode_val *temp;
739 gray 1.14 struct inode_val *e;
740    
741 gray 1.1 /* Create new inode record. */
742     temp = (struct inode_val *) xmalloc (sizeof (struct inode_val));
743     temp->inode = node_num;
744     temp->major_num = major_num;
745     temp->minor_num = minor_num;
746     temp->file_name = xstrdup (file_name);
747    
748 gray 1.14 if (!((hash_table
749     || (hash_table = hash_initialize (0, 0, inode_val_hasher,
750     inode_val_compare, 0)))
751     && (e = hash_insert (hash_table, temp))))
752     xalloc_die ();
753     /* FIXME: e is not used */
754 gray 1.1 }
755    
756    
757     /* Open FILE in the mode specified by the command line options
758     and return an open file descriptor for it,
759     or -1 if it can't be opened. */
760    
761     int
762 gray 1.4 open_archive (char *file)
763 gray 1.1 {
764     int fd;
765     void (*copy_in) (); /* Workaround for pcc bug. */
766    
767     copy_in = process_copy_in;
768    
769     if (copy_function == copy_in)
770 gray 1.8 fd = rmtopen (file, O_RDONLY | O_BINARY, MODE_RW, rsh_command_option);
771 gray 1.1 else
772     {
773     if (!append_flag)
774 gray 1.8 fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, MODE_RW,
775 gray 1.1 rsh_command_option);
776     else
777 gray 1.8 fd = rmtopen (file, O_RDWR | O_BINARY, MODE_RW, rsh_command_option);
778 gray 1.1 }
779    
780     return fd;
781     }
782    
783     /* Attempt to rewind the tape drive on file descriptor TAPE_DES
784     and take it offline. */
785    
786     void
787 gray 1.4 tape_offline (int tape_des)
788 gray 1.1 {
789     #if defined(MTIOCTOP) && defined(MTOFFL)
790     struct mtop control;
791    
792     control.mt_op = MTOFFL;
793     control.mt_count = 1;
794 gray 1.4 rmtioctl (tape_des, MTIOCTOP, (char*) &control); /* Don't care if it fails. */
795 gray 1.1 #endif
796     }
797    
798     /* The file on file descriptor TAPE_DES is assumed to be magnetic tape
799     (or floppy disk or other device) and the end of the medium
800     has been reached. Ask the user for to mount a new "tape" to continue
801     the processing. If the user specified the device name on the
802     command line (with the -I, -O, -F or --file options), then we can
803     automatically re-open the same device to use the next medium. If the
804     user did not specify the device name, then we have to ask them which
805     device to use. */
806    
807     void
808 gray 1.4 get_next_reel (int tape_des)
809 gray 1.1 {
810     static int reel_number = 1;
811     FILE *tty_in; /* File for interacting with user. */
812     FILE *tty_out; /* File for interacting with user. */
813     int old_tape_des;
814     char *next_archive_name;
815     dynamic_string new_name;
816     char *str_res;
817    
818     ds_init (&new_name, 128);
819    
820     /* Open files for interactive communication. */
821 gray 1.4 tty_in = fopen (TTY_NAME, "r");
822 gray 1.1 if (tty_in == NULL)
823 gray 1.4 error (2, errno, TTY_NAME);
824     tty_out = fopen (TTY_NAME, "w");
825 gray 1.1 if (tty_out == NULL)
826 gray 1.4 error (2, errno, TTY_NAME);
827 gray 1.1
828     old_tape_des = tape_des;
829     tape_offline (tape_des);
830     rmtclose (tape_des);
831    
832     /* Give message and wait for carrage return. User should hit carrage return
833     only after loading the next tape. */
834     ++reel_number;
835     if (new_media_message)
836     fprintf (tty_out, "%s", new_media_message);
837     else if (new_media_message_with_number)
838     fprintf (tty_out, "%s%d%s", new_media_message_with_number, reel_number,
839     new_media_message_after_number);
840     else if (archive_name)
841     fprintf (tty_out, _("Found end of tape. Load next tape and press RETURN. "));
842     else
843     fprintf (tty_out, _("Found end of tape. To continue, type device/file name when ready.\n"));
844    
845     fflush (tty_out);
846    
847     if (archive_name)
848     {
849     int c;
850    
851     do
852     c = getc (tty_in);
853     while (c != EOF && c != '\n');
854    
855     tape_des = open_archive (archive_name);
856     if (tape_des == -1)
857 gray 1.12 open_error (archive_name);
858 gray 1.1 }
859     else
860     {
861     do
862     {
863     if (tape_des < 0)
864     {
865     fprintf (tty_out,
866     _("To continue, type device/file name when ready.\n"));
867     fflush (tty_out);
868     }
869    
870     str_res = ds_fgets (tty_in, &new_name);
871     if (str_res == NULL || str_res[0] == '\0')
872     exit (1);
873     next_archive_name = str_res;
874    
875     tape_des = open_archive (next_archive_name);
876     if (tape_des == -1)
877 gray 1.12 open_error (next_archive_name);
878 gray 1.1 }
879     while (tape_des < 0);
880     }
881    
882     /* We have to make sure that `tape_des' has not changed its value even
883     though we closed it and reopened it, since there are local
884     copies of it in other routines. This works fine on Unix (even with
885     rmtread and rmtwrite) since open will always return the lowest
886     available file descriptor and we haven't closed any files (e.g.,
887     stdin, stdout or stderr) that were opened before we originally opened
888     the archive. */
889    
890     if (tape_des != old_tape_des)
891     error (1, 0, _("internal error: tape descriptor changed from %d to %d"),
892     old_tape_des, tape_des);
893    
894     free (new_name.ds_string);
895     fclose (tty_in);
896     fclose (tty_out);
897     }
898    
899     /* If MESSAGE does not contain the string "%d", make `new_media_message'
900     a copy of MESSAGE. If MESSAGES does contain the string "%d", make
901     `new_media_message_with_number' a copy of MESSAGE up to, but
902     not including, the string "%d", and make `new_media_message_after_number'
903     a copy of MESSAGE after the string "%d". */
904    
905     void
906 gray 1.4 set_new_media_message (char *message)
907 gray 1.1 {
908     char *p;
909     int prev_was_percent;
910    
911     p = message;
912     prev_was_percent = 0;
913     while (*p != '\0')
914     {
915     if (*p == 'd' && prev_was_percent)
916     break;
917     prev_was_percent = (*p == '%');
918     ++p;
919     }
920     if (*p == '\0')
921     {
922     new_media_message = xstrdup (message);
923     }
924     else
925     {
926     int length = p - message - 1;
927    
928     new_media_message_with_number = xmalloc (length + 1);
929     strncpy (new_media_message_with_number, message, length);
930     new_media_message_with_number[length] = '\0';
931     length = strlen (p + 1);
932     new_media_message_after_number = xmalloc (length + 1);
933     strcpy (new_media_message_after_number, p + 1);
934     }
935     }
936    
937     #ifdef SYMLINK_USES_UMASK
938     /* Most machines always create symlinks with rwxrwxrwx protection,
939     but some (HP/UX 8.07; maybe DEC's OSF on MIPS, too?) use the
940     umask when creating symlinks, so if your umask is 022 you end
941     up with rwxr-xr-x symlinks (although HP/UX seems to completely
942     ignore the protection). There doesn't seem to be any way to
943     manipulate the modes once the symlinks are created (e.g.
944     a hypothetical "lchmod"), so to create them with the right
945     modes we have to set the umask first. */
946    
947     int
948 gray 1.4 umasked_symlink (char *name1, char *name2, int mode)
949 gray 1.1 {
950     int old_umask;
951     int rc;
952     mode = ~(mode & 0777) & 0777;
953     old_umask = umask (mode);
954     rc = symlink (name1, name2);
955     umask (old_umask);
956     return rc;
957     }
958     #endif /* SYMLINK_USES_UMASK */
959    
960     #ifdef HPUX_CDF
961     /* When we create a cpio archive we mark CDF's by putting an extra `/'
962     after their component name so we can distinguish the CDF's when we
963     extract the archive (in case the "hidden" directory's files appear
964     in the archive before the directory itself). E.g., in the path
965     "a/b+/c", if b+ is a CDF, we will write this path as "a/b+//c" in
966     the archive so when we extract the archive we will know that b+
967     is actually a CDF, and not an ordinary directory whose name happens
968     to end in `+'. We also do the same thing internally in copypass.c. */
969    
970    
971     /* Take an input pathname and check it for CDF's. Insert an extra
972     `/' in the pathname after each "hidden" directory. If we add
973 gray 1.15 any `/'s, return a malloced string instead of the original input
974     string.
975     FIXME: This creates a memory leak.
976     */
977 gray 1.1
978     char *
979 gray 1.4 add_cdf_double_slashes (char *input_name)
980 gray 1.1 {
981     static char *ret_name = NULL; /* re-usuable return buffer (malloc'ed) */
982     static int ret_size = -1; /* size of return buffer. */
983     char *p;
984     char *q;
985     int n;
986     struct stat dir_stat;
987    
988     /* Search for a `/' preceeded by a `+'. */
989    
990     for (p = input_name; *p != '\0'; ++p)
991     {
992     if ( (*p == '+') && (*(p + 1) == '/') )
993     break;
994     }
995    
996     /* If we didn't find a `/' preceeded by a `+' then there are
997     no CDF's in this pathname. Return the original pathname. */
998    
999     if (*p == '\0')
1000     return input_name;
1001    
1002     /* There was a `/' preceeded by a `+' in the pathname. If it is a CDF
1003     then we will need to copy the input pathname to our return
1004     buffer so we can insert the extra `/'s. Since we can't tell
1005     yet whether or not it is a CDF we will just always copy the
1006     string to the return buffer. First we have to make sure the
1007     buffer is large enough to hold the string and any number of
1008     extra `/'s we might add. */
1009    
1010     n = 2 * (strlen (input_name) + 1);
1011     if (n >= ret_size)
1012     {
1013     if (ret_size < 0)
1014     ret_name = (char *) malloc (n);
1015     else
1016     ret_name = (char *)realloc (ret_name, n);
1017     ret_size = n;
1018     }
1019    
1020     /* Clear the `/' after this component, so we can stat the pathname
1021     up to and including this component. */
1022     ++p;
1023     *p = '\0';
1024     if ((*xstat) (input_name, &dir_stat) < 0)
1025     {
1026 gray 1.12 stat_error (input_name);
1027 gray 1.1 return input_name;
1028     }
1029    
1030     /* Now put back the `/' after this component and copy the pathname up to
1031     and including this component and its trailing `/' to the return
1032     buffer. */
1033     *p++ = '/';
1034     strncpy (ret_name, input_name, p - input_name);
1035     q = ret_name + (p - input_name);
1036    
1037     /* If it was a CDF, add another `/'. */
1038     if (S_ISDIR (dir_stat.st_mode) && (dir_stat.st_mode & 04000) )
1039     *q++ = '/';
1040    
1041     /* Go through the rest of the input pathname, copying it to the
1042     return buffer, and adding an extra `/' after each CDF. */
1043     while (*p != '\0')
1044     {
1045     if ( (*p == '+') && (*(p + 1) == '/') )
1046     {
1047     *q++ = *p++;
1048    
1049     *p = '\0';
1050     if ((*xstat) (input_name, &dir_stat) < 0)
1051     {
1052 gray 1.12 stat_error (input_name);
1053 gray 1.1 return input_name;
1054     }
1055     *p = '/';
1056    
1057     if (S_ISDIR (dir_stat.st_mode) && (dir_stat.st_mode & 04000) )
1058     *q++ = '/';
1059     }
1060     *q++ = *p++;
1061     }
1062     *q = '\0';
1063    
1064     return ret_name;
1065     }
1066    
1067     /* Is the last parent directory (e.g., c in a/b/c/d) a CDF? If the
1068     directory name ends in `+' and is followed by 2 `/'s instead of 1
1069     then it is. This is only the case for cpio archives, but we don't
1070     have to worry about tar because tar always has the directory before
1071     its files (or else we lose). */
1072 gray 1.4 int
1073     islastparentcdf (char *path)
1074 gray 1.1 {
1075     char *newpath;
1076     char *slash;
1077     int slash_count;
1078     int length; /* Length of result, not including NUL. */
1079    
1080 gray 1.7 slash = strrchr (path, '/');
1081 gray 1.1 if (slash == 0)
1082     return 0;
1083     else
1084     {
1085     slash_count = 0;
1086     while (slash > path && *slash == '/')
1087     {
1088     ++slash_count;
1089     --slash;
1090     }
1091    
1092    
1093     if ( (*slash == '+') && (slash_count >= 2) )
1094     return 1;
1095     }
1096     return 0;
1097     }
1098     #endif
1099    
1100     #define DISKBLOCKSIZE (512)
1101    
1102     static int
1103 gray 1.4 buf_all_zeros (char *buf, int bufsize)
1104 gray 1.1 {
1105     int i;
1106     for (i = 0; i < bufsize; ++i)
1107     {
1108     if (*buf++ != '\0')
1109     return 0;
1110     }
1111     return 1;
1112     }
1113    
1114     int delayed_seek_count = 0;
1115    
1116     /* Write NBYTE bytes from BUF to remote tape connection FILDES.
1117     Return the number of bytes written on success, -1 on error. */
1118    
1119 gray 1.22 static int
1120 gray 1.4 sparse_write (int fildes, char *buf, unsigned int nbyte)
1121 gray 1.1 {
1122     int complete_block_count;
1123     int leftover_bytes_count;
1124     int seek_count;
1125     int write_count;
1126     char *cur_write_start;
1127     int lseek_rc;
1128     int write_rc;
1129     int i;
1130 gray 1.22 enum { begin, in_zeros, not_in_zeros } state;
1131 gray 1.1
1132     complete_block_count = nbyte / DISKBLOCKSIZE;
1133     leftover_bytes_count = nbyte % DISKBLOCKSIZE;
1134    
1135     if (delayed_seek_count != 0)
1136     state = in_zeros;
1137     else
1138     state = begin;
1139    
1140     seek_count = delayed_seek_count;
1141    
1142     for (i = 0; i < complete_block_count; ++i)
1143     {
1144     switch (state)
1145     {
1146     case begin :
1147     if (buf_all_zeros (buf, DISKBLOCKSIZE))
1148     {
1149     seek_count = DISKBLOCKSIZE;
1150     state = in_zeros;
1151     }
1152     else
1153     {
1154     cur_write_start = buf;
1155     write_count = DISKBLOCKSIZE;
1156     state = not_in_zeros;
1157     }
1158     buf += DISKBLOCKSIZE;
1159     break;
1160 gray 1.22
1161 gray 1.1 case in_zeros :
1162     if (buf_all_zeros (buf, DISKBLOCKSIZE))
1163     {
1164     seek_count += DISKBLOCKSIZE;
1165     }
1166     else
1167     {
1168     lseek (fildes, seek_count, SEEK_CUR);
1169     cur_write_start = buf;
1170     write_count = DISKBLOCKSIZE;
1171     state = not_in_zeros;
1172     }
1173     buf += DISKBLOCKSIZE;
1174     break;
1175 gray 1.22
1176 gray 1.1 case not_in_zeros :
1177     if (buf_all_zeros (buf, DISKBLOCKSIZE))
1178     {
1179     write_rc = write (fildes, cur_write_start, write_count);
1180     seek_count = DISKBLOCKSIZE;
1181     state = in_zeros;
1182     }
1183     else
1184     {
1185     write_count += DISKBLOCKSIZE;
1186     }
1187     buf += DISKBLOCKSIZE;
1188     break;
1189     }
1190     }
1191    
1192     switch (state)
1193     {
1194     case begin :
1195     case in_zeros :
1196     delayed_seek_count = seek_count;
1197     break;
1198 gray 1.22
1199 gray 1.1 case not_in_zeros :
1200     write_rc = write (fildes, cur_write_start, write_count);
1201     delayed_seek_count = 0;
1202     break;
1203     }
1204    
1205     if (leftover_bytes_count != 0)
1206     {
1207     if (delayed_seek_count != 0)
1208     {
1209     lseek_rc = lseek (fildes, delayed_seek_count, SEEK_CUR);
1210     delayed_seek_count = 0;
1211     }
1212     write_rc = write (fildes, buf, leftover_bytes_count);
1213     }
1214     return nbyte;
1215     }
1216 gray 1.13
1217 gray 1.23 #define CPIO_UID(uid) (set_owner_flag ? set_owner : (uid))
1218 gray 1.25 #define CPIO_GID(gid) (set_group_flag ? set_group : (gid))
1219 gray 1.23
1220 gray 1.13 void
1221 gray 1.18 stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st)
1222 gray 1.13 {
1223     hdr->c_dev_maj = major (st->st_dev);
1224     hdr->c_dev_min = minor (st->st_dev);
1225     hdr->c_ino = st->st_ino;
1226     /* For POSIX systems that don't define the S_IF macros,
1227     we can't assume that S_ISfoo means the standard Unix
1228     S_IFfoo bit(s) are set. So do it manually, with a
1229     different name. Bleah. */
1230     hdr->c_mode = (st->st_mode & 07777);
1231     if (S_ISREG (st->st_mode))
1232     hdr->c_mode |= CP_IFREG;
1233     else if (S_ISDIR (st->st_mode))
1234     hdr->c_mode |= CP_IFDIR;
1235     #ifdef S_ISBLK
1236     else if (S_ISBLK (st->st_mode))
1237     hdr->c_mode |= CP_IFBLK;
1238     #endif
1239     #ifdef S_ISCHR
1240     else if (S_ISCHR (st->st_mode))
1241     hdr->c_mode |= CP_IFCHR;
1242     #endif
1243     #ifdef S_ISFIFO
1244     else if (S_ISFIFO (st->st_mode))
1245     hdr->c_mode |= CP_IFIFO;
1246     #endif
1247     #ifdef S_ISLNK
1248     else if (S_ISLNK (st->st_mode))
1249     hdr->c_mode |= CP_IFLNK;
1250     #endif
1251     #ifdef S_ISSOCK
1252     else if (S_ISSOCK (st->st_mode))
1253     hdr->c_mode |= CP_IFSOCK;
1254     #endif
1255     #ifdef S_ISNWK
1256     else if (S_ISNWK (st->st_mode))
1257     hdr->c_mode |= CP_IFNWK;
1258     #endif
1259 gray 1.23 hdr->c_uid = CPIO_UID (st->st_uid);
1260     hdr->c_gid = CPIO_GID (st->st_gid);
1261 gray 1.13 hdr->c_nlink = st->st_nlink;
1262     hdr->c_rdev_maj = major (st->st_rdev);
1263     hdr->c_rdev_min = minor (st->st_rdev);
1264     hdr->c_mtime = st->st_mtime;
1265     hdr->c_filesize = st->st_size;
1266     hdr->c_chksum = 0;
1267     hdr->c_tar_linkname = NULL;
1268     }
1269    
1270 gray 1.24 #ifndef HAVE_FCHOWN
1271 gray 1.29 # define HAVE_FCHOWN 0
1272     #endif
1273     #ifndef HAVE_FCHMOD
1274     # define HAVE_FCHMOD 0
1275 gray 1.24 #endif
1276    
1277     int
1278     fchown_or_chown (int fd, const char *name, uid_t uid, uid_t gid)
1279     {
1280     if (HAVE_FCHOWN && fd != -1)
1281     return fchown (fd, uid, gid);
1282     else
1283     return chown (name, uid, gid);
1284     }
1285    
1286     int
1287     fchmod_or_chmod (int fd, const char *name, mode_t mode)
1288     {
1289     if (HAVE_FCHMOD && fd != -1)
1290     return fchmod (fd, mode);
1291     else
1292     return chmod(name, mode);
1293     }
1294    
1295 gray 1.13 void
1296 gray 1.24 set_perms (int fd, struct cpio_file_stat *header)
1297 gray 1.13 {
1298     if (!no_chown_flag)
1299     {
1300 gray 1.23 uid_t uid = CPIO_UID (header->c_uid);
1301     gid_t gid = CPIO_GID (header->c_gid);
1302 gray 1.24 if ((fchown_or_chown (fd, header->c_name, uid, gid) < 0)
1303     && errno != EPERM)
1304 gray 1.13 chown_error_details (header->c_name, uid, gid);
1305     }
1306     /* chown may have turned off some permissions we wanted. */
1307 gray 1.24 if (fchmod_or_chmod (fd, header->c_name, header->c_mode) < 0)
1308 gray 1.13 chmod_error_details (header->c_name, header->c_mode);
1309     #ifdef HPUX_CDF
1310     if ((header->c_mode & CP_IFMT) && cdf_flag)
1311     /* Once we "hide" the directory with the chmod(),
1312     we have to refer to it using name+ instead of name. */
1313     file_hdr->c_name [cdf_char] = '+';
1314     #endif
1315     if (retain_time_flag)
1316 gray 1.24 set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime);
1317 gray 1.16 }
1318    
1319     void
1320 gray 1.24 set_file_times (int fd,
1321     const char *name, unsigned long atime, unsigned long mtime)
1322 gray 1.16 {
1323     struct timespec ts[2];
1324    
1325     memset (&ts, 0, sizeof ts);
1326    
1327     ts[0].tv_sec = atime;
1328     ts[1].tv_sec = mtime;
1329    
1330 gray 1.24 /* Silently ignore EROFS because reading the file won't have upset its
1331     timestamp if it's on a read-only filesystem. */
1332     if (gl_futimens (fd, name, ts) < 0 && errno != EROFS)
1333 gray 1.16 utime_error (name);
1334 gray 1.13 }
1335 gray 1.15
1336     /* Do we have to ignore absolute paths, and if so, does the filename
1337     have an absolute path? */
1338     void
1339     cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names,
1340     bool strip_leading_dots)
1341     {
1342     char *p = safer_name_suffix (name, link_target, absolute_names);
1343 gray 1.16 if (strip_leading_dots && strcmp (p, "./"))
1344 gray 1.15 /* strip leading `./' from the filename. */
1345     while (*p == '.' && *(p + 1) == '/')
1346     {
1347     ++p;
1348     while (*p == '/')
1349     ++p;
1350     }
1351     if (p != name)
1352     memmove (name, p, (size_t)(strlen (p) + 1));
1353     }
1354    
1355 gray 1.27
1356     /* This is a simplified form of delayed set_stat used by GNU tar.
1357     With the time, both forms will merge and pass to paxutils
1358    
1359     List of directories whose statuses we need to extract after we've
1360     finished extracting their subsidiary files. If you consider each
1361     contiguous subsequence of elements of the form [D]?[^D]*, where [D]
1362     represents an element where AFTER_LINKS is nonzero and [^D]
1363     represents an element where AFTER_LINKS is zero, then the head
1364     of the subsequence has the longest name, and each non-head element
1365     in the prefix is an ancestor (in the directory hierarchy) of the
1366     preceding element. */
1367    
1368     struct delayed_set_stat
1369     {
1370     struct delayed_set_stat *next;
1371     struct cpio_file_stat stat;
1372     mode_t invert_permissions;
1373     };
1374    
1375     static struct delayed_set_stat *delayed_set_stat_head;
1376    
1377     void
1378     delay_set_stat (char const *file_name, struct stat *st,
1379     mode_t invert_permissions)
1380     {
1381     size_t file_name_len = strlen (file_name);
1382     struct delayed_set_stat *data =
1383     xmalloc (sizeof (struct delayed_set_stat) + file_name_len + 1);
1384     data->next = delayed_set_stat_head;
1385     memset (&data->stat, 0, sizeof data->stat);
1386     stat_to_cpio (&data->stat, st);
1387     data->stat.c_name = (char*) (data + 1);
1388     strcpy (data->stat.c_name, file_name);
1389     data->invert_permissions = invert_permissions;
1390     delayed_set_stat_head = data;
1391     }
1392    
1393     /* Update the delayed_set_stat info for an intermediate directory
1394     created within the file name of DIR. The intermediate directory turned
1395     out to be the same as this directory, e.g. due to ".." or symbolic
1396     links. *DIR_STAT_INFO is the status of the directory. */
1397     void
1398     repair_delayed_set_stat (char const *dir,
1399     struct stat *dir_stat_info)
1400     {
1401     struct delayed_set_stat *data;
1402     for (data = delayed_set_stat_head; data; data = data->next)
1403     {
1404     struct stat st;
1405     if (stat (data->stat.c_name, &st) != 0)
1406     {
1407     stat_error (data->stat.c_name);
1408     return;
1409     }
1410    
1411     if (st.st_dev == dir_stat_info->st_dev
1412     && st.st_ino == dir_stat_info->st_ino)
1413     {
1414     stat_to_cpio (&data->stat, dir_stat_info);
1415     data->invert_permissions =
1416     ((dir_stat_info->st_mode ^ st.st_mode)
1417     & MODE_RWX & ~ newdir_umask);
1418     return;
1419     }
1420     }
1421    
1422     ERROR ((0, 0, _("%s: Unexpected inconsistency when making directory"),
1423     quotearg_colon (dir)));
1424     }
1425    
1426     void
1427     apply_delayed_set_stat ()
1428     {
1429     while (delayed_set_stat_head)
1430     {
1431     struct delayed_set_stat *data = delayed_set_stat_head;
1432     if (data->invert_permissions)
1433     {
1434 gray 1.28 data->stat.c_mode ^= data->invert_permissions;
1435 gray 1.27 }
1436     set_perms (-1, &data->stat);
1437     delayed_set_stat_head = data->next;
1438     free (data);
1439     }
1440     }

Send suggestions and bug reports to Sergey Poznyakoff
ViewVC Help
Powered by ViewVC 1.1.20