]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/cmd/pax/fileio.c
ape: bring strtod() in line with plan9's libc version
[plan9front.git] / sys / src / ape / cmd / pax / fileio.c
1 /* $Source: /u/mark/src/pax/RCS/fileio.c,v $
2  *
3  * $Revision: 1.2 $
4  *
5  * fileio.c - file I/O functions for all archive interfaces
6  *
7  * DESCRIPTION
8  *
9  *      These function all do I/O of some form or another.  They are
10  *      grouped here mainly for convienence.
11  *
12  * AUTHOR
13  *
14  *      Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
15  *
16  * Sponsored by The USENIX Association for public distribution. 
17  *
18  * Copyright (c) 1989 Mark H. Colburn.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms are permitted
22  * provided that the above copyright notice is duplicated in all such 
23  * forms and that any documentation, advertising materials, and other 
24  * materials related to such distribution and use acknowledge that the 
25  * software was developed * by Mark H. Colburn and sponsored by The 
26  * USENIX Association. 
27  *
28  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31  *
32  * $Log:        fileio.c,v $
33  * Revision 1.2  89/02/12  10:04:31  mark
34  * 1.2 release fixes
35  * 
36  * Revision 1.1  88/12/23  18:02:09  mark
37  * Initial revision
38  * 
39  */
40
41 #ifndef lint
42 static char *ident = "$Id: fileio.c,v 1.2 89/02/12 10:04:31 mark Exp $";
43 static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
44 #endif /* ! lint */
45
46
47 /* Headers */
48
49 #include "pax.h"
50
51
52 /* open_archive -  open an archive file.  
53  *
54  * DESCRIPTION
55  *
56  *      Open_archive will open an archive file for reading or writing,
57  *      setting the proper file mode, depending on the "mode" passed to
58  *      it.  All buffer pointers are reset according to the mode
59  *      specified.
60  *
61  * PARAMETERS
62  *
63  *      int     mode    - specifies whether we are reading or writing.   
64  *
65  * RETURNS
66  *
67  *      Returns a zero if successfull, or -1 if an error occured during 
68  *      the open.
69  */
70
71 #ifdef __STDC__
72     
73 int open_archive(int mode)
74
75 #else
76     
77 int open_archive(mode)
78 int             mode;
79
80 #endif
81 {
82     if (ar_file[0] == '-' && ar_file[1] == '\0') {
83         if (mode == AR_READ) {
84             archivefd = STDIN;
85             bufend = bufidx = bufstart;
86         } else {
87             archivefd = STDOUT;
88         }
89     } else if (mode == AR_READ) {
90         archivefd = open(ar_file, O_RDONLY | O_BINARY);
91         bufend = bufidx = bufstart;     /* set up for initial read */
92     } else if (mode == AR_WRITE) {
93         archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
94     } else if (mode == AR_APPEND) {
95         archivefd = open(ar_file, O_RDWR | O_BINARY, 0666);
96         bufend = bufidx = bufstart;     /* set up for initial read */
97     }
98
99     if (archivefd < 0) {
100         warnarch(strerror(), (OFFSET) 0);
101         return (-1);
102     }
103     ++arvolume;
104     return (0);
105 }
106
107
108 /* close_archive - close the archive file
109  *
110  * DESCRIPTION
111  *
112  *      Closes the current archive and resets the archive end of file
113  *      marker.
114  */
115
116 #ifdef __STDC__
117
118 void close_archive(void)
119
120 #else
121     
122 void close_archive()
123
124 #endif
125 {
126     if (archivefd != STDIN && archivefd != STDOUT) {
127         close(archivefd);
128     }
129     areof = 0;
130 }
131
132
133 /* openout - open an output file
134  *
135  * DESCRIPTION
136  *
137  *      Openo opens the named file for output.  The file mode and type are
138  *      set based on the values stored in the stat structure for the file.
139  *      If the file is a special file, then no data will be written, the
140  *      file/directory/Fifo, etc., will just be created.  Appropriate
141  *      permission may be required to create special files.
142  *
143  * PARAMETERS
144  *
145  *      char    *name           - The name of the file to create
146  *      Stat    *asb            - Stat structure for the file
147  *      Link    *linkp;         - pointer to link chain for this file
148  *      int      ispass         - true if we are operating in "pass" mode
149  *
150  * RETURNS
151  *
152  *      Returns the output file descriptor, 0 if no data is required or -1 
153  *      if unsuccessful. Note that UNIX open() will never return 0 because 
154  *      the standard input is in use. 
155  */
156
157 #ifdef __STDC__
158
159 int openout(char *name, Stat *asb, Link *linkp, int ispass)
160
161 #else
162     
163 int openout(name, asb, linkp, ispass)
164 char           *name;
165 Stat           *asb;
166 Link           *linkp;
167 int             ispass;
168
169 #endif
170 {
171     int             exists;
172     int             fd;
173     ushort          perm;
174     ushort          operm = 0;
175     Stat            osb;
176 #ifdef  S_IFLNK
177     int             ssize;
178     char            sname[PATH_MAX + 1];
179 #endif  /* S_IFLNK */
180
181     if (exists = (LSTAT(name, &osb) == 0)) {
182         if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
183             warn(name, "Same file");
184             return (-1);
185         } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
186             operm = osb.sb_mode & S_IPERM;
187         } else if (REMOVE(name, &osb) < 0) {
188             warn(name, strerror());
189             return (-1);
190         } else {
191             exists = 0;
192         }
193     }
194     if (linkp) {
195         if (exists) {
196             if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
197                 return (0);
198             } else if (unlink(name) < 0) {
199                 warn(name, strerror());
200                 return (-1);
201             } else {
202                 exists = 0;
203             }
204         }
205         if (link(linkp->l_name, name) != 0) {
206             if (errno == ENOENT) {
207                 if (f_dir_create) {
208                     if (dirneed(name) != 0 ||
209                             link(linkp->l_name, name) != 0) {
210                             warn(name, strerror());
211                         return (-1);
212                     }
213                 } else {
214                     warn(name, 
215                              "Directories are not being created (-d option)");
216                 }
217                 return(0);
218             } else if (errno != EXDEV) {
219                 warn(name, strerror());
220                 return (-1);
221             }
222         } else {
223             return(0);
224         } 
225     }
226     perm = asb->sb_mode & S_IPERM;
227     switch (asb->sb_mode & S_IFMT) {
228     case S_IFBLK:
229     case S_IFCHR:
230 #ifdef _POSIX_SOURCE
231         warn(name, "Can't create special files");
232         return (-1);
233 #else
234         fd = 0;
235         if (exists) {
236             if (asb->sb_rdev == osb.sb_rdev) {
237                 if (perm != operm && chmod(name, (int) perm) < 0) {
238                     warn(name, strerror());
239                     return (-1);
240                 } else {
241                     break;
242                 }
243             } else if (REMOVE(name, &osb) < 0) {
244                 warn(name, strerror());
245                 return (-1);
246             } else {
247                 exists = 0;
248             }
249         }
250         if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
251             if (errno == ENOENT) {
252                 if (f_dir_create) {
253                     if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode, 
254                            (int) asb->sb_rdev) < 0) {
255                         warn(name, strerror());
256                         return (-1);
257                     }
258                 } else {
259                     warn(name, "Directories are not being created (-d option)");
260                 }
261             } else {
262                 warn(name, strerror());
263                 return (-1);
264             }
265         }
266         return(0);
267 #endif /* _POSIX_SOURCE */
268         break;
269     case S_IFDIR:
270         if (exists) {
271             if (perm != operm && chmod(name, (int) perm) < 0) {
272                 warn(name, strerror());
273                 return (-1);
274             }
275         } else if (f_dir_create) {
276             if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
277                 warn(name, strerror());
278                 return (-1);
279             }
280         } else {
281             warn(name, "Directories are not being created (-d option)");
282         }
283         return (0);
284 #ifndef _POSIX_SOURCE
285 #ifdef  S_IFIFO
286     case S_IFIFO:
287         fd = 0;
288         if (exists) {
289             if (perm != operm && chmod(name, (int) perm) < 0) {
290                 warn(name, strerror());
291                 return (-1);
292             }
293         } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
294             if (errno == ENOENT) {
295                 if (f_dir_create) {
296                     if (dirneed(name) < 0
297                        || mknod(name, (int) asb->sb_mode, 0) < 0) {
298                         warn(name, strerror());
299                         return (-1);
300                     }
301                 } else {
302                     warn(name, "Directories are not being created (-d option)");
303                 }
304             } else {
305                 warn(name, strerror());
306                 return (-1);
307             }
308         }
309         return(0);
310         break;
311 #endif                          /* S_IFIFO */
312 #endif                          /* _POSIX_SOURCE */
313 #ifdef  S_IFLNK
314     case S_IFLNK:
315         if (exists) {
316             if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
317                 warn(name, strerror());
318                 return (-1);
319             } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
320                 return (0);
321             } else if (REMOVE(name, &osb) < 0) {
322                 warn(name, strerror());
323                 return (-1);
324             } else {
325                 exists = 0;
326             }
327         }
328         if (symlink(asb->sb_link, name) < 0) {
329             if (errno == ENOENT) {
330                 if (f_dir_create) {
331                     if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
332                         warn(name, strerror());
333                         return (-1);
334                     }
335                 } else {
336                     warn(name, "Directories are not being created (-d option)");
337                 }
338             } else {
339                 warn(name, strerror());
340                 return (-1);
341             }
342         }
343         return (0);             /* Can't chown()/chmod() a symbolic link */
344 #endif                          /* S_IFLNK */
345     case S_IFREG:
346         if (exists) {
347             if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
348                 warn(name, "Newer file exists");
349                 return (-1);
350             } else if (unlink(name) < 0) {
351                 warn(name, strerror());
352                 return (-1);
353             } else {
354                 exists = 0;
355             }
356         }
357         if ((fd = creat(name, (int) perm)) < 0) {
358             if (errno == ENOENT) {
359                 if (f_dir_create) {
360                     if (dirneed(name) < 0 || 
361                             (fd = creat(name, (int) perm)) < 0) {
362                         warn(name, strerror());
363                         return (-1);
364                     }
365                 } else {
366                     /* 
367                      * the file requires a directory which does not exist
368                      * and which the user does not want created, so skip
369                      * the file...
370                      */
371                     warn(name, "Directories are not being created (-d option)");
372                     return(0);
373                 }
374             } else {
375                 warn(name, strerror());
376                 return (-1);
377             }
378         }
379         break;
380     default:
381         warn(name, "Unknown filetype");
382         return (-1);
383     }
384     if (f_owner) {
385         if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
386             chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
387         }
388     }
389     return (fd);
390 }
391
392
393 /* openin - open the next input file
394  *
395  * DESCRIPTION
396  *
397  *      Openi will attempt to open the next file for input.  If the file is
398  *      a special file, such as a directory, FIFO, link, character- or
399  *      block-special file, then the file size field of the stat structure
400  *      is zeroed to make sure that no data is written out for the file.
401  *      If the file is a special file, then a file descriptor of 0 is
402  *      returned to the caller, which is handled specially.  If the file
403  *      is a regular file, then the file is opened and a file descriptor
404  *      to the open file is returned to the caller.
405  *
406  * PARAMETERS
407  *
408  *      char   *name    - pointer to the name of the file to open
409  *      Stat   *asb     - pointer to the stat block for the file to open
410  *
411  * RETURNS
412  *
413  *      Returns a file descriptor, 0 if no data exists, or -1 at EOF. This 
414  *      kludge works because standard input is in use, preventing open() from 
415  *      returning zero. 
416  */
417
418 #ifdef __STDC__
419
420 int openin(char *name, Stat *asb)
421
422 #else
423     
424 int openin(name, asb)
425 char           *name;           /* name of file to open */
426 Stat           *asb;            /* pointer to stat structure for file */
427
428 #endif
429 {
430     int             fd;
431
432     switch (asb->sb_mode & S_IFMT) {
433     case S_IFDIR:
434         asb->sb_nlink = 1;
435         asb->sb_size = 0;
436         return (0);
437 #ifdef  S_IFLNK
438     case S_IFLNK:
439         if ((asb->sb_size = readlink(name,
440                              asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
441             warn(name, strerror());
442             return(0);
443         }
444         asb->sb_link[asb->sb_size] = '\0';
445         return (0);
446 #endif                          /* S_IFLNK */
447     case S_IFREG:
448         if (asb->sb_size == 0) {
449             return (0);
450         }
451         if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
452             warn(name, strerror());
453         }
454         return (fd);
455     default:
456         asb->sb_size = 0;
457         return (0);
458     }
459 }