Annotation of /trunk/libarchive/patches/libarchive-2.7.0-pipe.patch
Parent Directory | Revision Log
Revision 842 -
(hide annotations)
(download)
Thu Jun 11 18:52:50 2009 UTC (15 years, 3 months ago) by niro
File size: 3859 byte(s)
Thu Jun 11 18:52:50 2009 UTC (15 years, 3 months ago) by niro
File size: 3859 byte(s)
-added libarchive patches
1 | niro | 842 | --- head/lib/libarchive/archive_read_open_filename.c 2009/05/07 21:51:13 191903 |
2 | +++ head/lib/libarchive/archive_read_open_filename.c 2009/05/07 23:01:03 191904 | ||
3 | @@ -85,19 +85,31 @@ | ||
4 | int fd; | ||
5 | |||
6 | - if (filename == NULL || filename[0] == '\0') | ||
7 | - return (archive_read_open_fd(a, 0, block_size)); | ||
8 | - | ||
9 | - fd = open(filename, O_RDONLY | O_BINARY); | ||
10 | - if (fd < 0) { | ||
11 | - archive_set_error(a, errno, "Failed to open '%s'", filename); | ||
12 | - return (ARCHIVE_FATAL); | ||
13 | + if (filename == NULL || filename[0] == '\0') { | ||
14 | + /* We used to invoke archive_read_open_fd(a,0,block_size) | ||
15 | + * here, but that doesn't (and shouldn't) handle the | ||
16 | + * end-of-file flush when reading stdout from a pipe. | ||
17 | + * Basically, read_open_fd() is intended for folks who | ||
18 | + * are willing to handle such details themselves. This | ||
19 | + * API is intended to be a little smarter for folks who | ||
20 | + * want easy handling of the common case. | ||
21 | + */ | ||
22 | + filename = ""; /* Normalize NULL to "" */ | ||
23 | + fd = 0; | ||
24 | + } else { | ||
25 | + fd = open(filename, O_RDONLY | O_BINARY); | ||
26 | + if (fd < 0) { | ||
27 | + archive_set_error(a, errno, | ||
28 | + "Failed to open '%s'", filename); | ||
29 | + return (ARCHIVE_FATAL); | ||
30 | + } | ||
31 | } | ||
32 | if (fstat(fd, &st) != 0) { | ||
33 | archive_set_error(a, errno, "Can't stat '%s'", filename); | ||
34 | return (ARCHIVE_FATAL); | ||
35 | } | ||
36 | |||
37 | - mine = (struct read_file_data *)malloc(sizeof(*mine) + strlen(filename)); | ||
38 | + mine = (struct read_file_data *)calloc(1, | ||
39 | + sizeof(*mine) + strlen(filename)); | ||
40 | b = malloc(block_size); | ||
41 | if (mine == NULL || b == NULL) { | ||
42 | archive_set_error(a, ENOMEM, "No memory"); | ||
43 | @@ -117,15 +129,20 @@ | ||
44 | if (S_ISREG(st.st_mode)) { | ||
45 | archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); | ||
46 | /* | ||
47 | - * Skip is a performance optimization for anything | ||
48 | - * that supports lseek(). Generally, that only | ||
49 | - * includes regular files and possibly raw disk | ||
50 | - * devices, but there's no good portable way to detect | ||
51 | - * raw disks. | ||
52 | + * Enabling skip here is a performance optimization | ||
53 | + * for anything that supports lseek(). On FreeBSD | ||
54 | + * (and probably many other systems), only regular | ||
55 | + * files and raw disk devices support lseek() (on | ||
56 | + * other input types, lseek() returns success but | ||
57 | + * doesn't actually change the file pointer, which | ||
58 | + * just completely screws up the position-tracking | ||
59 | + * logic). In addition, I've yet to find a portable | ||
60 | + * way to determine if a device is a raw disk device. | ||
61 | + * So I don't see a way to do much better than to only | ||
62 | + * enable this optimization for regular files. | ||
63 | */ | ||
64 | mine->can_skip = 1; | ||
65 | - } else | ||
66 | - mine->can_skip = 0; | ||
67 | + } | ||
68 | return (archive_read_open2(a, mine, | ||
69 | NULL, file_read, file_skip, file_close)); | ||
70 | } | ||
71 | @@ -139,8 +156,11 @@ | ||
72 | *buff = mine->buffer; | ||
73 | bytes_read = read(mine->fd, mine->buffer, mine->block_size); | ||
74 | if (bytes_read < 0) { | ||
75 | - archive_set_error(a, errno, "Error reading '%s'", | ||
76 | - mine->filename); | ||
77 | + if (mine->filename[0] == '\0') | ||
78 | + archive_set_error(a, errno, "Error reading stdin"); | ||
79 | + else | ||
80 | + archive_set_error(a, errno, "Error reading '%s'", | ||
81 | + mine->filename); | ||
82 | } | ||
83 | return (bytes_read); | ||
84 | } | ||
85 | @@ -190,8 +210,15 @@ | ||
86 | * likely caused by a programmer error (too large request) | ||
87 | * or a corrupted archive file. | ||
88 | */ | ||
89 | - archive_set_error(a, errno, "Error seeking in '%s'", | ||
90 | - mine->filename); | ||
91 | + if (mine->filename[0] == '\0') | ||
92 | + /* | ||
93 | + * Should never get here, since lseek() on stdin ought | ||
94 | + * to return an ESPIPE error. | ||
95 | + */ | ||
96 | + archive_set_error(a, errno, "Error seeking in stdin"); | ||
97 | + else | ||
98 | + archive_set_error(a, errno, "Error seeking in '%s'", | ||
99 | + mine->filename); | ||
100 | return (-1); | ||
101 | } | ||
102 | return (new_offset - old_offset); | ||
103 | @@ -225,7 +252,9 @@ | ||
104 | mine->block_size); | ||
105 | } while (bytesRead > 0); | ||
106 | } | ||
107 | - close(mine->fd); | ||
108 | + /* If a named file was opened, then it needs to be closed. */ | ||
109 | + if (mine->filename[0] != '\0') | ||
110 | + close(mine->fd); | ||
111 | } | ||
112 | free(mine->buffer); | ||
113 | free(mine); |