summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2000-06-16 04:56:40 +0000
committerEric Andersen <andersen@codepoet.org>2000-06-16 04:56:40 +0000
commit852ff13fc43e99737c89ced1485c19bfbe0714bb (patch)
tree723d3428fb43cb75d8ac394201c2b3e1a06923c4
parentb9913954054b87f64f0a8010a2d67f0ffd7f5b86 (diff)
downloadbusybox-w32-852ff13fc43e99737c89ced1485c19bfbe0714bb.tar.gz
busybox-w32-852ff13fc43e99737c89ced1485c19bfbe0714bb.tar.bz2
busybox-w32-852ff13fc43e99737c89ced1485c19bfbe0714bb.zip
Update to ar.c from Glenn McGrath. His comments follow:
------------------------------ the attached diff applies to the ar.c i originally submitted Changes Preserve dates now works. Extracted files are set to the uid, gid and mode specified in the archive. Checks for valid end of header marker. Correctly unpacks newer debian files. (has a '\n' character between entries) Added more comments. Cleaned up code. Added a last modified date to help keep track of versions. TODO Common functionality in ar.c are in tar.c should be merged, in particular getOctal and extractSubFile. Should all functions that are used by multiple file go in utilities.c ?
-rw-r--r--ar.c229
-rw-r--r--archival/ar.c229
2 files changed, 284 insertions, 174 deletions
diff --git a/ar.c b/ar.c
index 253f3348a..e58b7395d 100644
--- a/ar.c
+++ b/ar.c
@@ -21,6 +21,7 @@
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * 23 *
24 * Last modified 10 June 2000
24 */ 25 */
25 26
26 27
@@ -28,9 +29,18 @@
28#include <fcntl.h> 29#include <fcntl.h>
29#include <errno.h> 30#include <errno.h>
30#include <ctype.h> 31#include <ctype.h>
32#include <time.h>
33#include <utime.h>
34#include <sys/types.h>
31#include "internal.h" 35#include "internal.h"
32 36
33#define AR_BLOCK_SIZE 60 37#define AR_BLOCK_SIZE 60
38#define AR_PRESERVE_DATE 1
39#define AR_VERBOSE 2
40#define AR_DISPLAY 4
41#define AR_EXT_TO_FILE 8
42#define AR_EXT_TO_STDOUT 16
43
34#define BB_DECLARE_EXTERN 44#define BB_DECLARE_EXTERN
35#define bb_need_io_error 45#define bb_need_io_error
36#include "messages.c" 46#include "messages.c"
@@ -67,22 +77,50 @@ static const char ar_usage[] = "ar [optxvV] archive [filenames] \n"
67#endif 77#endif
68 ; 78 ;
69 79
70static void displayContents(struct ArInfo *entry, int funct) 80/*
81 * Display details of a file, verbosly if funct=2
82 */
83static void displayEntry(struct ArInfo *entry, int funct)
71{ 84{
72 /* TODO convert mode to string */ 85 /* TODO convert mode to string */
73 if ((funct & 2) == 2) 86 if ((funct & AR_VERBOSE) == AR_VERBOSE)
74 printf("%i %i/%i %6i %s ", entry->mode, entry->uid, entry->gid, 87 printf("%i %i/%i %8i %s ", entry->mode, entry->uid, entry->gid,
75 entry->size, timeString(entry->date)); 88 entry->size, timeString(entry->date));
76 printf("%s\n", entry->name); 89 printf("%s\n", entry->name);
77} 90}
78 91
79/* Converts to new typed struct */ 92/* this is from tar.c remove later*/
80static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header) 93static long getOctal(const char *cp, int size)
94{
95 long val = 0;
96
97 for(;(size > 0) && (*cp == ' '); cp++, size--);
98 if ((size == 0) || !isOctal(*cp))
99 return -1;
100 for(; (size > 0) && isOctal(*cp); size--) {
101 val = val * 8 + *cp++ - '0';
102 }
103 for (;(size > 0) && (*cp == ' '); cp++, size--);
104 if ((size > 0) && *cp)
105 return -1;
106 return val;
107}
108
109/*
110 * Converts from the char based struct to a new struct with stricter types
111 */
112static int processArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
81{ 113{
82 int count2; 114 int count2;
83 int count; 115 int count;
116
117 /* check end of header marker is valid */
118 if ((rawHeader->ar_fmag[0]!='`') || (rawHeader->ar_fmag[1]!='\n'))
119 return(FALSE);
84 120
121 /* convert filename */
85 for (count = 0; count < 16; count++) { 122 for (count = 0; count < 16; count++) {
123 /* allow spaces in filename except at the end */
86 if (rawHeader->ar_name[count] == ' ') { 124 if (rawHeader->ar_name[count] == ' ') {
87 for (count2 = count; count2 < 16; count2++) 125 for (count2 = count; count2 < 16; count2++)
88 if (!isspace(rawHeader->ar_name[count2])) 126 if (!isspace(rawHeader->ar_name[count2]))
@@ -90,6 +128,7 @@ static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
90 if (count2 >= 16) 128 if (count2 >= 16)
91 break; 129 break;
92 } 130 }
131 /* GNU ar uses '/' as an end of filename marker */
93 if (rawHeader->ar_name[count] == '/') 132 if (rawHeader->ar_name[count] == '/')
94 break; 133 break;
95 header->name[count] = rawHeader->ar_name[count]; 134 header->name[count] = rawHeader->ar_name[count];
@@ -98,15 +137,14 @@ static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
98 header->date = atoi(rawHeader->ar_date); 137 header->date = atoi(rawHeader->ar_date);
99 header->uid = atoi(rawHeader->ar_uid); 138 header->uid = atoi(rawHeader->ar_uid);
100 header->gid = atoi(rawHeader->ar_gid); 139 header->gid = atoi(rawHeader->ar_gid);
101 header->mode = atoi(rawHeader->ar_mode); 140 header->mode = getOctal(rawHeader->ar_mode, sizeof(rawHeader->ar_mode));
102 header->size = atoi(rawHeader->ar_size); 141 header->size = atoi(rawHeader->ar_size);
103 return (TRUE); 142 return (TRUE);
104} 143}
105 144
106/* 145/*
107 * Copy size bytes from current position if srcFd to current position in dstFd 146 * Copy size bytes from current position if srcFd to current position in dstFd
108 * taken from tarExtractRegularFile in tar.c 147 * taken from tarExtractRegularFile in tar.c, remove later
109 * could be used for ar, tar and copyFile .
110 */ 148 */
111static int copySubFile(int srcFd, int dstFd, int copySize) 149static int copySubFile(int srcFd, int dstFd, int copySize)
112{ 150{
@@ -134,17 +172,16 @@ static int copySubFile(int srcFd, int dstFd, int copySize)
134} 172}
135 173
136/* 174/*
137 * Need to add checks, stat newfile before creation,change mode from 0777 175 * Extract the file described in ArInfo to the specified path
138 * extract to current dir 176 * set the new files uid, gid and mode
139 * dstStat.st_size copied from current position of file pointed to by srcFd
140 */ 177 */
141static int extractToFile(int srcFd, const char *path, const char *name, 178static int extractToFile(struct ArInfo *file, int funct, int srcFd, const char *path)
142 int size)
143{ 179{
144 int dstFd, temp; 180 int dstFd, temp;
145 struct stat tmpStat; 181 struct stat tmpStat;
146 char *pathname = NULL; 182 char *pathname = NULL;
147 183 struct utimbuf newtime;
184
148 if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) { 185 if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) {
149 if (!createPath(path, 0777)) { 186 if (!createPath(path, 0777)) {
150 fatalError("Cannot extract to specified path"); 187 fatalError("Cannot extract to specified path");
@@ -154,95 +191,108 @@ static int extractToFile(int srcFd, const char *path, const char *name,
154 temp = (strlen(path) + 16); 191 temp = (strlen(path) + 16);
155 pathname = (char *) xmalloc(temp); 192 pathname = (char *) xmalloc(temp);
156 pathname = strcpy(pathname, path); 193 pathname = strcpy(pathname, path);
157 pathname = strcat(pathname, &name[0]); 194 pathname = strcat(pathname, file->name);
158 dstFd = device_open(pathname, O_WRONLY | O_CREAT); 195 dstFd = device_open(pathname, O_WRONLY | O_CREAT);
159 pathname = NULL; 196 temp = copySubFile(srcFd, dstFd, file->size);
160 temp = copySubFile(srcFd, dstFd, size); 197 fchown(dstFd, file->uid, file->gid);
198 fchmod(dstFd, file->mode);
161 close(dstFd); 199 close(dstFd);
200 if ((funct&AR_PRESERVE_DATE)==AR_PRESERVE_DATE)
201 newtime.modtime=file->date;
202 else
203 newtime.modtime=time(0);
204 newtime.actime=time(0);
205 temp = utime(pathname, &newtime);
162 return (TRUE); 206 return (TRUE);
163} 207}
164 208
165/* Step through the ar file entries */ 209/*
166static int readArFile(char **fileNames, int argc, int funct) 210 * Return a file descriptor for the specified file and do error checks
211 */
212static int getArFd(char *filename)
167{ 213{
168 int arFd = 0; 214 int arFd;
169 int pdates = 0; 215 char arVersion[8];
170 int verbose = 0;
171 int display = 0;
172 int extract = 0;
173 int extToStdout = 0;
174 int status = 0;
175 int found = 0;
176 ArHeader rawArHeader;
177 ArInfo arEntry;
178 char arVersion[8];
179 char *arName;
180 char *selName[argc - 2];
181 int i;
182 216
183 if ((funct & 1) == 1) 217 arFd = open(filename, O_RDONLY);
184 pdates = 1; 218 if (arFd < 0) {
185 if ((funct & 2) == 2) 219 errorMsg("Error opening '%s': %s\n", filename, strerror(errno));
186 verbose = 1;
187 if ((funct & 4) == 4)
188 display = 1;
189 if ((funct & 16) == 16) { /* extract to stdout */
190 extract = 1;
191 extToStdout = 1;
192 }
193 if ((funct & 8) == 8) { /* extract to file */
194 extract = 1;
195 }
196 arName = fileNames[2];
197 for (i = 0; i < (argc - 3); i++)
198 selName[i] = fileNames[i + 3];
199 arFd = open(arName, O_RDONLY);
200 if (arFd < 0) {
201 errorMsg("Error opening '%s': %s\n", arName, strerror(errno));
202 return (FALSE);
203 }
204 if (fullRead(arFd, arVersion, 8) <= 0) {
205 errorMsg("ar: Unexpected EOF in archive\n");
206 return (FALSE);
207 }
208 if (strncmp(arVersion, "!<arch>", 7) != 0) {
209 errorMsg("ar header fails check ");
210 return (FALSE); 220 return (FALSE);
211 } 221 }
222 if (fullRead(arFd, arVersion, 8) <= 0) {
223 errorMsg( "ar: Unexpected EOF in archive\n");
224 return (FALSE);
225 }
226 if (strncmp(arVersion,"!<arch>",7) != 0) {
227 errorMsg("ar header fails check ");
228 return(FALSE);
229 }
230 return arFd;
231}
232
233/*
234 * Step through the ar file and process it one entry at a time
235 * fileList[0] is the name of the ar archive
236 * fileList[1] and up are filenames to extract from the archive
237 * funct contains flags to specify the actions to be performed
238 */
239static int readArFile(char *fileList[16], int fileListSize, int funct)
240{
241 int arFd, status, extFileFlag, i, lastOffset=0;
242 ArHeader rawArHeader;
243 ArInfo arEntry;
244
245 /* open the ar archive */
246 arFd=getArFd(fileList[0]);
247
248 /* read the first header, then loop until ono more headers */
212 while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE)) 249 while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE))
213 == AR_BLOCK_SIZE) { 250 == AR_BLOCK_SIZE) {
214 readArHeader(&rawArHeader, &arEntry);
215 251
216 if (display == 1) { 252 /* check the header is valid, if not try reading the header
217 displayContents(&arEntry, funct); 253 agian with an offset of 1, needed as some ar archive end
218 } 254 with a '\n' which isnt counted in specified file size */
219 if (argc == 3) 255 if ((status=processArHeader(&rawArHeader, &arEntry))==FALSE ) {
220 found = 1; 256 if ((i=lseek(arFd, 0, SEEK_CUR))==(lastOffset+60))
221 else { 257 lseek(arFd, lastOffset+1, SEEK_SET);
222 found = 0; 258 else
223 for (i = 0; i < (argc - 3); i++) { 259 return(FALSE);
224 if ((status = (strcmp(selName[i], arEntry.name))) == 0) 260 }
225 found = 1; 261 else {
226 } 262 extFileFlag=0;
227 } 263
228 if ((extract == 1) && (found == 1)) { 264 if (funct&AR_DISPLAY)
229 if (extToStdout == 1) { 265 displayEntry(&arEntry, funct);
230 copySubFile(arFd, fileno(stdout), arEntry.size); 266
231 } else { 267 /* check file was specified to be extracted only if
232 extractToFile(arFd, "./", arEntry.name, arEntry.size); 268 some file were specified */
269 if ((funct&AR_EXT_TO_FILE) || (funct&AR_EXT_TO_STDOUT)){
270 if (fileListSize==1)
271 extFileFlag=1;
272 else {
273 for( i=1; i<=fileListSize; i++)
274 if ((status=(strcmp(fileList[i],arEntry.name)))==0)
275 extFileFlag=1;
276 }
233 } 277 }
234 } else 278 if (extFileFlag==1) {
235 lseek(arFd, arEntry.size, SEEK_CUR); 279 if (funct&AR_EXT_TO_FILE)
236 } 280 extractToFile(&arEntry, funct, arFd, "./");
237 return (0); 281 else
282 copySubFile(arFd,fileno(stdout),arEntry.size);
283 }
284 else
285 lseek(arFd, arEntry.size, SEEK_CUR);
286 lastOffset=lseek(arFd, 0, SEEK_CUR);
287 } /* if processArHeader */
288 } /* while */
289 return (TRUE);
238} 290}
239 291
240extern int ar_main(int argc, char **argv) 292extern int ar_main(int argc, char **argv)
241{ 293{
242 int ret = 0; 294 int funct = 0, ret=0, i=0;
243 char *opt_ptr; 295 char *fileList[16], c, *opt_ptr;
244 char c;
245 int funct = 0;
246 296
247 if (argc < 2) 297 if (argc < 2)
248 usage(ar_usage); 298 usage(ar_usage);
@@ -271,7 +321,12 @@ extern int ar_main(int argc, char **argv)
271 usage(ar_usage); 321 usage(ar_usage);
272 } 322 }
273 } 323 }
324
325 for(i=0; i<(argc-2); i++)
326 fileList[i]=argv[i+2];
327
274 if (funct > 3) 328 if (funct > 3)
275 ret = readArFile(argv, argc, funct); 329 ret = readArFile(fileList, (argc-2), funct);
330
276 return (ret); 331 return (ret);
277} 332}
diff --git a/archival/ar.c b/archival/ar.c
index 253f3348a..e58b7395d 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -21,6 +21,7 @@
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * 23 *
24 * Last modified 10 June 2000
24 */ 25 */
25 26
26 27
@@ -28,9 +29,18 @@
28#include <fcntl.h> 29#include <fcntl.h>
29#include <errno.h> 30#include <errno.h>
30#include <ctype.h> 31#include <ctype.h>
32#include <time.h>
33#include <utime.h>
34#include <sys/types.h>
31#include "internal.h" 35#include "internal.h"
32 36
33#define AR_BLOCK_SIZE 60 37#define AR_BLOCK_SIZE 60
38#define AR_PRESERVE_DATE 1
39#define AR_VERBOSE 2
40#define AR_DISPLAY 4
41#define AR_EXT_TO_FILE 8
42#define AR_EXT_TO_STDOUT 16
43
34#define BB_DECLARE_EXTERN 44#define BB_DECLARE_EXTERN
35#define bb_need_io_error 45#define bb_need_io_error
36#include "messages.c" 46#include "messages.c"
@@ -67,22 +77,50 @@ static const char ar_usage[] = "ar [optxvV] archive [filenames] \n"
67#endif 77#endif
68 ; 78 ;
69 79
70static void displayContents(struct ArInfo *entry, int funct) 80/*
81 * Display details of a file, verbosly if funct=2
82 */
83static void displayEntry(struct ArInfo *entry, int funct)
71{ 84{
72 /* TODO convert mode to string */ 85 /* TODO convert mode to string */
73 if ((funct & 2) == 2) 86 if ((funct & AR_VERBOSE) == AR_VERBOSE)
74 printf("%i %i/%i %6i %s ", entry->mode, entry->uid, entry->gid, 87 printf("%i %i/%i %8i %s ", entry->mode, entry->uid, entry->gid,
75 entry->size, timeString(entry->date)); 88 entry->size, timeString(entry->date));
76 printf("%s\n", entry->name); 89 printf("%s\n", entry->name);
77} 90}
78 91
79/* Converts to new typed struct */ 92/* this is from tar.c remove later*/
80static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header) 93static long getOctal(const char *cp, int size)
94{
95 long val = 0;
96
97 for(;(size > 0) && (*cp == ' '); cp++, size--);
98 if ((size == 0) || !isOctal(*cp))
99 return -1;
100 for(; (size > 0) && isOctal(*cp); size--) {
101 val = val * 8 + *cp++ - '0';
102 }
103 for (;(size > 0) && (*cp == ' '); cp++, size--);
104 if ((size > 0) && *cp)
105 return -1;
106 return val;
107}
108
109/*
110 * Converts from the char based struct to a new struct with stricter types
111 */
112static int processArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
81{ 113{
82 int count2; 114 int count2;
83 int count; 115 int count;
116
117 /* check end of header marker is valid */
118 if ((rawHeader->ar_fmag[0]!='`') || (rawHeader->ar_fmag[1]!='\n'))
119 return(FALSE);
84 120
121 /* convert filename */
85 for (count = 0; count < 16; count++) { 122 for (count = 0; count < 16; count++) {
123 /* allow spaces in filename except at the end */
86 if (rawHeader->ar_name[count] == ' ') { 124 if (rawHeader->ar_name[count] == ' ') {
87 for (count2 = count; count2 < 16; count2++) 125 for (count2 = count; count2 < 16; count2++)
88 if (!isspace(rawHeader->ar_name[count2])) 126 if (!isspace(rawHeader->ar_name[count2]))
@@ -90,6 +128,7 @@ static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
90 if (count2 >= 16) 128 if (count2 >= 16)
91 break; 129 break;
92 } 130 }
131 /* GNU ar uses '/' as an end of filename marker */
93 if (rawHeader->ar_name[count] == '/') 132 if (rawHeader->ar_name[count] == '/')
94 break; 133 break;
95 header->name[count] = rawHeader->ar_name[count]; 134 header->name[count] = rawHeader->ar_name[count];
@@ -98,15 +137,14 @@ static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
98 header->date = atoi(rawHeader->ar_date); 137 header->date = atoi(rawHeader->ar_date);
99 header->uid = atoi(rawHeader->ar_uid); 138 header->uid = atoi(rawHeader->ar_uid);
100 header->gid = atoi(rawHeader->ar_gid); 139 header->gid = atoi(rawHeader->ar_gid);
101 header->mode = atoi(rawHeader->ar_mode); 140 header->mode = getOctal(rawHeader->ar_mode, sizeof(rawHeader->ar_mode));
102 header->size = atoi(rawHeader->ar_size); 141 header->size = atoi(rawHeader->ar_size);
103 return (TRUE); 142 return (TRUE);
104} 143}
105 144
106/* 145/*
107 * Copy size bytes from current position if srcFd to current position in dstFd 146 * Copy size bytes from current position if srcFd to current position in dstFd
108 * taken from tarExtractRegularFile in tar.c 147 * taken from tarExtractRegularFile in tar.c, remove later
109 * could be used for ar, tar and copyFile .
110 */ 148 */
111static int copySubFile(int srcFd, int dstFd, int copySize) 149static int copySubFile(int srcFd, int dstFd, int copySize)
112{ 150{
@@ -134,17 +172,16 @@ static int copySubFile(int srcFd, int dstFd, int copySize)
134} 172}
135 173
136/* 174/*
137 * Need to add checks, stat newfile before creation,change mode from 0777 175 * Extract the file described in ArInfo to the specified path
138 * extract to current dir 176 * set the new files uid, gid and mode
139 * dstStat.st_size copied from current position of file pointed to by srcFd
140 */ 177 */
141static int extractToFile(int srcFd, const char *path, const char *name, 178static int extractToFile(struct ArInfo *file, int funct, int srcFd, const char *path)
142 int size)
143{ 179{
144 int dstFd, temp; 180 int dstFd, temp;
145 struct stat tmpStat; 181 struct stat tmpStat;
146 char *pathname = NULL; 182 char *pathname = NULL;
147 183 struct utimbuf newtime;
184
148 if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) { 185 if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) {
149 if (!createPath(path, 0777)) { 186 if (!createPath(path, 0777)) {
150 fatalError("Cannot extract to specified path"); 187 fatalError("Cannot extract to specified path");
@@ -154,95 +191,108 @@ static int extractToFile(int srcFd, const char *path, const char *name,
154 temp = (strlen(path) + 16); 191 temp = (strlen(path) + 16);
155 pathname = (char *) xmalloc(temp); 192 pathname = (char *) xmalloc(temp);
156 pathname = strcpy(pathname, path); 193 pathname = strcpy(pathname, path);
157 pathname = strcat(pathname, &name[0]); 194 pathname = strcat(pathname, file->name);
158 dstFd = device_open(pathname, O_WRONLY | O_CREAT); 195 dstFd = device_open(pathname, O_WRONLY | O_CREAT);
159 pathname = NULL; 196 temp = copySubFile(srcFd, dstFd, file->size);
160 temp = copySubFile(srcFd, dstFd, size); 197 fchown(dstFd, file->uid, file->gid);
198 fchmod(dstFd, file->mode);
161 close(dstFd); 199 close(dstFd);
200 if ((funct&AR_PRESERVE_DATE)==AR_PRESERVE_DATE)
201 newtime.modtime=file->date;
202 else
203 newtime.modtime=time(0);
204 newtime.actime=time(0);
205 temp = utime(pathname, &newtime);
162 return (TRUE); 206 return (TRUE);
163} 207}
164 208
165/* Step through the ar file entries */ 209/*
166static int readArFile(char **fileNames, int argc, int funct) 210 * Return a file descriptor for the specified file and do error checks
211 */
212static int getArFd(char *filename)
167{ 213{
168 int arFd = 0; 214 int arFd;
169 int pdates = 0; 215 char arVersion[8];
170 int verbose = 0;
171 int display = 0;
172 int extract = 0;
173 int extToStdout = 0;
174 int status = 0;
175 int found = 0;
176 ArHeader rawArHeader;
177 ArInfo arEntry;
178 char arVersion[8];
179 char *arName;
180 char *selName[argc - 2];
181 int i;
182 216
183 if ((funct & 1) == 1) 217 arFd = open(filename, O_RDONLY);
184 pdates = 1; 218 if (arFd < 0) {
185 if ((funct & 2) == 2) 219 errorMsg("Error opening '%s': %s\n", filename, strerror(errno));
186 verbose = 1;
187 if ((funct & 4) == 4)
188 display = 1;
189 if ((funct & 16) == 16) { /* extract to stdout */
190 extract = 1;
191 extToStdout = 1;
192 }
193 if ((funct & 8) == 8) { /* extract to file */
194 extract = 1;
195 }
196 arName = fileNames[2];
197 for (i = 0; i < (argc - 3); i++)
198 selName[i] = fileNames[i + 3];
199 arFd = open(arName, O_RDONLY);
200 if (arFd < 0) {
201 errorMsg("Error opening '%s': %s\n", arName, strerror(errno));
202 return (FALSE);
203 }
204 if (fullRead(arFd, arVersion, 8) <= 0) {
205 errorMsg("ar: Unexpected EOF in archive\n");
206 return (FALSE);
207 }
208 if (strncmp(arVersion, "!<arch>", 7) != 0) {
209 errorMsg("ar header fails check ");
210 return (FALSE); 220 return (FALSE);
211 } 221 }
222 if (fullRead(arFd, arVersion, 8) <= 0) {
223 errorMsg( "ar: Unexpected EOF in archive\n");
224 return (FALSE);
225 }
226 if (strncmp(arVersion,"!<arch>",7) != 0) {
227 errorMsg("ar header fails check ");
228 return(FALSE);
229 }
230 return arFd;
231}
232
233/*
234 * Step through the ar file and process it one entry at a time
235 * fileList[0] is the name of the ar archive
236 * fileList[1] and up are filenames to extract from the archive
237 * funct contains flags to specify the actions to be performed
238 */
239static int readArFile(char *fileList[16], int fileListSize, int funct)
240{
241 int arFd, status, extFileFlag, i, lastOffset=0;
242 ArHeader rawArHeader;
243 ArInfo arEntry;
244
245 /* open the ar archive */
246 arFd=getArFd(fileList[0]);
247
248 /* read the first header, then loop until ono more headers */
212 while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE)) 249 while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE))
213 == AR_BLOCK_SIZE) { 250 == AR_BLOCK_SIZE) {
214 readArHeader(&rawArHeader, &arEntry);
215 251
216 if (display == 1) { 252 /* check the header is valid, if not try reading the header
217 displayContents(&arEntry, funct); 253 agian with an offset of 1, needed as some ar archive end
218 } 254 with a '\n' which isnt counted in specified file size */
219 if (argc == 3) 255 if ((status=processArHeader(&rawArHeader, &arEntry))==FALSE ) {
220 found = 1; 256 if ((i=lseek(arFd, 0, SEEK_CUR))==(lastOffset+60))
221 else { 257 lseek(arFd, lastOffset+1, SEEK_SET);
222 found = 0; 258 else
223 for (i = 0; i < (argc - 3); i++) { 259 return(FALSE);
224 if ((status = (strcmp(selName[i], arEntry.name))) == 0) 260 }
225 found = 1; 261 else {
226 } 262 extFileFlag=0;
227 } 263
228 if ((extract == 1) && (found == 1)) { 264 if (funct&AR_DISPLAY)
229 if (extToStdout == 1) { 265 displayEntry(&arEntry, funct);
230 copySubFile(arFd, fileno(stdout), arEntry.size); 266
231 } else { 267 /* check file was specified to be extracted only if
232 extractToFile(arFd, "./", arEntry.name, arEntry.size); 268 some file were specified */
269 if ((funct&AR_EXT_TO_FILE) || (funct&AR_EXT_TO_STDOUT)){
270 if (fileListSize==1)
271 extFileFlag=1;
272 else {
273 for( i=1; i<=fileListSize; i++)
274 if ((status=(strcmp(fileList[i],arEntry.name)))==0)
275 extFileFlag=1;
276 }
233 } 277 }
234 } else 278 if (extFileFlag==1) {
235 lseek(arFd, arEntry.size, SEEK_CUR); 279 if (funct&AR_EXT_TO_FILE)
236 } 280 extractToFile(&arEntry, funct, arFd, "./");
237 return (0); 281 else
282 copySubFile(arFd,fileno(stdout),arEntry.size);
283 }
284 else
285 lseek(arFd, arEntry.size, SEEK_CUR);
286 lastOffset=lseek(arFd, 0, SEEK_CUR);
287 } /* if processArHeader */
288 } /* while */
289 return (TRUE);
238} 290}
239 291
240extern int ar_main(int argc, char **argv) 292extern int ar_main(int argc, char **argv)
241{ 293{
242 int ret = 0; 294 int funct = 0, ret=0, i=0;
243 char *opt_ptr; 295 char *fileList[16], c, *opt_ptr;
244 char c;
245 int funct = 0;
246 296
247 if (argc < 2) 297 if (argc < 2)
248 usage(ar_usage); 298 usage(ar_usage);
@@ -271,7 +321,12 @@ extern int ar_main(int argc, char **argv)
271 usage(ar_usage); 321 usage(ar_usage);
272 } 322 }
273 } 323 }
324
325 for(i=0; i<(argc-2); i++)
326 fileList[i]=argv[i+2];
327
274 if (funct > 3) 328 if (funct > 3)
275 ret = readArFile(argv, argc, funct); 329 ret = readArFile(fileList, (argc-2), funct);
330
276 return (ret); 331 return (ret);
277} 332}