]>
Dogcows Code - chaz/tar/blob - src/port.c
1 /* Supporting routines which may sometimes be missing.
2 Copyright (C) 1988, 1992 Free Software Foundation
4 This file is part of GNU Tar.
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <sys/types.h>
41 /* All machine-dependent #ifdefs should appear here, instead of
42 being scattered through the file. For UN*X systems, it is better to
43 figure out what is needed in the configure script, for most of the
47 char TTY_NAME
[] = "con";
52 char TTY_NAME
[] = "/dev/tty";
55 /* End of system-dependent #ifdefs */
60 * valloc() does a malloc() on a page boundary. On some systems,
61 * this can make large block I/O more efficient.
67 return (malloc (size
));
70 #endif /* !HAVE_VALLOC */
74 * Written by Robert Rother, Mariah Corporation, August 1985.
76 * If you want it, it's yours. All I ask in return is that if you
77 * figure out how to do this in a Bourne Shell script you send me
79 * sdcsvax!rmr or rmr@uscd
81 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
82 * subroutine. 11Mar86; hoptoad!gnu
84 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
85 * subroutine didn't return EEXIST. It does now.
99 if (stat (dpath
, &statbuf
) == 0)
101 errno
= EEXIST
; /* Stat worked, so it already exists */
105 /* If stat fails for a reason other than non-existence, return error */
109 switch (cpid
= fork ())
112 case -1: /* Error in fork() */
113 return (-1); /* Errno is set already */
115 case 0: /* Child process */
117 * Cheap hack to set mode of new directory. Since this
118 * child process is going away anyway, we zap its umask.
119 * FIXME, this won't suffice to set SUID, SGID, etc. on this
120 * directory. Does anybody care?
122 status
= umask (0); /* Get current umask */
123 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
124 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
125 _exit (-1); /* Can't exec /bin/mkdir */
127 default: /* Parent process */
128 while (cpid
!= wait (&status
)); /* Wait for kid to finish */
131 if (WIFSIGNALED (status
) || WEXITSTATUS (status
) != 0)
133 errno
= EIO
; /* We don't know why, but */
134 return -1; /* /bin/mkdir failed */
147 if (stat (dpath
, &statbuf
) != 0)
149 /* Stat just set errno. We don't have to */
153 switch (cpid
= fork ())
156 case -1: /* Error in fork() */
157 return (-1); /* Errno is set already */
159 case 0: /* Child process */
160 execl ("/bin/rmdir", "rmdir", dpath
, (char *) 0);
161 _exit (-1); /* Can't exec /bin/mkdir */
163 default: /* Parent process */
164 while (cpid
!= wait (&status
)); /* Wait for kid to finish */
167 if (WIFSIGNALED (status
) || WEXITSTATUS (status
) != 0)
169 errno
= EIO
; /* We don't know why, but */
170 return -1; /* /bin/mkdir failed */
176 #endif /* !HAVE_MKDIR */
179 /* Rename file FROM to file TO.
180 Return 0 if successful, -1 if not. */
187 struct stat from_stats
;
189 if (stat (from
, &from_stats
))
192 if (unlink (to
) && errno
!= ENOENT
)
198 if (unlink (from
) && errno
!= ENOENT
)
207 #endif /* !HAVE_RENAME */
210 /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
220 /* It also has no bcmp() */
223 register char *s1
, *s2
;
226 for (; n
--; ++s1
, ++s2
)
235 * Groan, Minix doesn't have execlp either!
237 * execlp(file,arg0,arg1...argn,(char *)NULL)
238 * exec a program, automatically searching for the program through
239 * all the directories on the PATH.
241 * This version is naive about variable argument lists, it assumes
242 * a straightforward C calling sequence. If your system has odd stacks
243 * *and* doesn't have execlp, YOU get to fix it.
246 execlp (filename
, arg0
)
247 char *filename
, *arg0
;
249 register char *p
, *path
;
250 register char *fnbuffer
;
251 char **argstart
= &arg0
;
253 extern char **environ
;
255 if ((p
= getenv ("PATH")) == NULL
)
257 /* couldn't find path variable -- try to exec given filename */
258 return execve (filename
, argstart
, environ
);
262 * make a place to build the filename. We malloc larger than we
263 * need, but we know it will fit in this.
265 fnbuffer
= malloc (strlen (p
) + 1 + strlen (filename
));
266 if (fnbuffer
== NULL
)
273 * try each component of the path to see if the file's there
276 for (path
= p
; path
; path
= p
)
278 /* construct full path name to try */
279 if ((p
= index (path
, ':')) == NULL
)
281 strcpy (fnbuffer
, path
);
285 strncpy (fnbuffer
, path
, p
- path
);
286 fnbuffer
[p
- path
] = '\0';
287 p
++; /* Skip : for next time */
289 if (strlen (fnbuffer
) != 0)
290 strcat (fnbuffer
, "/");
291 strcat (fnbuffer
, filename
);
293 /* check to see if file is there and is a normal file */
294 if (stat (fnbuffer
, &statbuf
) < 0)
297 continue; /* file not there,keep on looking */
299 goto fail
; /* failed for some reason, return */
301 if (!S_ISREG (statbuf
.st_mode
))
304 if (execve (fnbuffer
, argstart
, environ
) < 0
308 /* failed, for some other reason besides "file
309 * not found" or "not a.out format"
315 * If we got error ENOEXEC, the file is executable but is
316 * not an object file. Try to execute it as a shell script,
317 * returning error if we can't execute /bin/sh.
319 * FIXME, this code is broken in several ways. Shell
320 * scripts should not in general be executed by the user's
321 * SHELL variable program. On more mature systems, the
322 * script can specify with #!/bin/whatever. Also, this
323 * code clobbers argstart[-1] if the exec of the shell
326 if (errno
== ENOEXEC
)
330 /* Try to execute command "sh arg0 arg1 ..." */
331 if ((shell
= getenv ("SHELL")) == NULL
)
333 argstart
[-1] = shell
;
334 argstart
[0] = fnbuffer
;
335 execve (shell
, &argstart
[-1], environ
);
336 goto fail
; /* Exec didn't work */
340 * If we succeeded, the execve() doesn't return, so we
341 * can only be here is if the file hasn't been found yet.
342 * Try the next place on the path.
346 /* all attempts failed to locate the file. Give up. */
360 * open3 -- routine to emulate the 3-argument open system
361 * call that is present in most modern Unix systems.
362 * This version attempts to support all the flag bits except for O_NDELAY
363 * and O_APPEND, which are silently ignored. The emulation is not as efficient
364 * as the real thing (at worst, 4 system calls instead of one), but there's
365 * not much I can do about that.
367 * Written 6/10/87 by rmtodd@uokmax
369 * open3(path, flag, mode)
370 * Attempts to open the file specified by
371 * the given pathname. The following flag bits (#defined in tar.h)
372 * specify options to the routine:
373 * O_RDONLY file open for read only
374 * O_WRONLY file open for write only
375 * O_RDWR file open for both read & write
376 * (Needless to say, you should only specify one of the above).
377 * O_CREAT file is created with specified mode if it needs to be.
378 * O_TRUNC if file exists, it is truncated to 0 bytes
379 * O_EXCL used with O_CREAT--routine returns error if file exists
380 * Function returns file descriptor if successful, -1 and errno if not.
384 * array to give arguments to access for various modes
385 * FIXME, this table depends on the specific integer values of O_XXX,
386 * and also contains integers (args to 'access') that should be #define's.
393 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
396 /* Shut off the automatic emulation of open(), we'll need it. */
400 open3 (path
, flags
, mode
)
408 * We actually do the work by calling the open() or creat() system
409 * call, depending on the flags. Call_creat is true if we will use
410 * creat(), false if we will use open().
414 * See if the file exists and is accessible in the requested mode.
416 * Strictly speaking we shouldn't be using access, since access checks
417 * against real uid, and the open call should check against euid.
418 * Most cases real uid == euid, so it won't matter. FIXME.
419 * FIXME, the construction "flags & 3" and the modes table depends
420 * on the specific integer values of the O_XXX #define's. Foo!
422 if (access (path
, modes
[flags
& 3]) < 0)
426 /* the file does not exist */
431 /* probably permission violation */
434 /* Oops, the file exists, we didn't want it. */
435 /* No matter what the error, claim EEXIST. */
442 /* if we have the O_CREAT bit set, check for O_EXCL */
445 if ((flags
& O_EXCL
) && exists
)
447 /* Oops, the file exists and we didn't want it to. */
452 * If the file doesn't exist, be sure to call creat() so that
453 * it will be created with the proper mode.
460 /* If O_CREAT isn't set and the file doesn't exist, error. */
469 * If the O_TRUNC flag is set and the file exists, we want to call
470 * creat() anyway, since creat() guarantees that the file will be
471 * truncated and open()-for-writing doesn't.
472 * (If the file doesn't exist, we're calling creat() anyway and the
473 * file will be created with zero length.)
475 if ((flags
& O_TRUNC
) && exists
)
477 /* actually do the call */
481 * call creat. May have to close and reopen the file if we
482 * want O_RDONLY or O_RDWR access -- creat() only gives
485 fd
= creat (path
, mode
);
486 if (fd
< 0 || (flags
& O_WRONLY
))
490 /* Fall out to reopen the file we've created */
494 * calling old open, we strip most of the new flags just in case.
496 return open (path
, flags
& (O_RDONLY
| O_WRONLY
| O_RDWR
| O_BINARY
));
499 #endif /* EMUL_OPEN3 */
505 /* Fake mknod by complaining */
507 mknod (path
, mode
, dev
)
514 errno
= ENXIO
; /* No such device or address */
515 return -1; /* Just give an error */
518 /* Fake links by copying */
529 fprintf (stderr
, "%s: %s: cannot link to %s, copying instead\n",
531 if ((ifd
= open (path1
, O_RDONLY
| O_BINARY
)) < 0)
533 if ((ofd
= creat (path2
, 0666)) < 0)
535 setmode (ofd
, O_BINARY
);
536 while ((nrbytes
= read (ifd
, buf
, sizeof (buf
))) > 0)
538 if ((nwbytes
= write (ofd
, buf
, nrbytes
)) != nrbytes
)
544 /* Note use of "|" rather than "||" below: we want to close
545 * the files even if an error occurs.
547 if ((nrbytes
< 0) | (0 != close (ifd
)) | (0 != close (ofd
)))
555 /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
557 chown (path
, uid
, gid
)
571 #endif /* !HAVE_MKNOD */
580 time_t actime
; /* Access time. */
581 time_t modtime
; /* Modification time. */
585 utime (char *filename
, struct utimbuf
*utb
)
588 struct ftime filetime
;
598 fd
= _open (filename
, O_RDWR
);
602 tm
= localtime (&when
);
603 if (tm
->tm_year
< 80)
604 filetime
.ft_year
= 0;
606 filetime
.ft_year
= tm
->tm_year
- 80;
607 filetime
.ft_month
= tm
->tm_mon
+ 1;
608 filetime
.ft_day
= tm
->tm_mday
;
610 filetime
.ft_hour
= 0;
612 filetime
.ft_hour
= tm
->tm_hour
;
613 filetime
.ft_min
= tm
->tm_min
;
614 filetime
.ft_tsec
= tm
->tm_sec
/ 2;
616 status
= setftime (fd
, &filetime
);
621 #endif /* __TURBOC__ */
623 /* Stash argv[0] here so panic will know what the program is called */
631 fprintf (stderr
, "%s:", myname
);
648 panic ("Couldn't allocate memory");
652 /* Used by alloca.c and bison.simple. */
657 return (char *) ck_malloc (size
);
661 ck_realloc (ptr
, size
)
668 ret
= ck_malloc (size
);
670 ret
= realloc (ptr
, size
);
672 panic ("Couldn't re-allocate memory");
676 /* Implement a variable sized buffer of 'stuff'. We don't know what it is,
677 nor do we care, as long as it doesn't mind being aligned on a char boundry.
687 #define MIN_ALLOCATE 50
694 b
= (struct buffer
*) ck_malloc (sizeof (struct buffer
));
695 b
->allocated
= MIN_ALLOCATE
;
696 b
->b
= (char *) ck_malloc (MIN_ALLOCATE
);
707 b
= (struct buffer
*) bb
;
716 add_buffer (bb
, p
, n
)
723 b
= (struct buffer
*) bb
;
724 if (b
->length
+ n
> b
->allocated
)
726 b
->allocated
= b
->length
+ n
+ MIN_ALLOCATE
;
727 b
->b
= (char *) ck_realloc (b
->b
, b
->allocated
);
729 bcopy (p
, b
->b
+ b
->length
, n
);
739 b
= (struct buffer
*) bb
;
744 merge_sort (list
, n
, off
, cmp
)
753 unsigned alength
, blength
;
758 #define NEXTOF(ptr) (* ((char **)(((char *)(ptr))+off) ) )
763 if ((*cmp
) (list
, NEXTOF (list
)) > 0)
773 alength
= (n
+ 1) / 2;
775 for (tptr
= list
, tmp
= (n
- 1) / 2; tmp
; tptr
= NEXTOF (tptr
), tmp
--)
777 blist
= NEXTOF (tptr
);
780 alist
= merge_sort (alist
, alength
, off
, cmp
);
781 blist
= merge_sort (blist
, blength
, off
, cmp
);
783 for (; alist
&& blist
;)
785 if ((*cmp
) (alist
, blist
) < 0)
787 tptr
= NEXTOF (alist
);
789 prev
= &(NEXTOF (alist
));
794 tptr
= NEXTOF (blist
);
796 prev
= &(NEXTOF (blist
));
814 msg_perror ("can't close a file #%d", fd
);
821 /* Quote_copy_string is like quote_string, but instead of modifying the
822 string in place, it malloc-s a copy of the string, and returns that.
823 If the string does not have to be quoted, it returns the NULL string.
824 The allocated copy can, of course, be freed with free() after the
825 caller is done with it.
828 quote_copy_string (string
)
847 n
= (from_here
- string
) - 1;
849 copy_buf
= (char *) malloc (n
+ 5 + strlen (from_here
) * 4);
852 bcopy (string
, copy_buf
, n
);
853 to_there
= copy_buf
+ n
;
858 else if (isprint (c
))
869 n
= (from_here
- string
) - 1;
871 copy_buf
= (char *) malloc (n
+ 5 + strlen (from_here
) * 4);
874 bcopy (string
, copy_buf
, n
);
875 to_there
= copy_buf
+ n
;
888 else if (c
== '\177')
892 to_there
[0] = (c
>> 6) + '0';
893 to_there
[1] = ((c
>> 3) & 07) + '0';
894 to_there
[2] = (c
& 07) + '0';
908 /* Un_quote_string takes a quoted c-string (like those produced by
909 quote_string or quote_copy_string and turns it back into the
910 un-quoted original. This is done in place.
913 /* There is no un-quote-copy-string. Write it yourself */
916 un_quote_string (string
)
929 if (*from_here
!= '\\')
931 if (from_here
!= to_there
)
932 *to_there
++ = *from_here
++;
934 from_here
++, to_there
++;
937 switch (*++from_here
)
940 *to_there
++ = *from_here
++;
974 tmp
= *from_here
- '0';
976 if (*from_here
< '0' || *from_here
> '7')
981 tmp
= tmp
* 8 + *from_here
- '0';
983 if (*from_here
< '0' || *from_here
> '7')
988 tmp
= tmp
* 8 + *from_here
- '0';
995 *to_there
++ = *from_here
++;
1009 if (pipe (pipes
) < 0)
1011 msg_perror ("can't open a pipe");
1015 #endif /* !__MSDOS__ */
1019 * strstr - find first occurrence of wanted in s
1022 char * /* found string, or NULL if none */
1027 register char *scan
;
1028 register size_t len
;
1029 register char firstc
;
1031 if (*wanted
== '\0')
1034 * The odd placement of the two tests is so "" is findable.
1035 * Also, we inline the first char for speed.
1036 * The ++ on scan has been moved down for optimization.
1039 len
= strlen (wanted
);
1040 for (scan
= s
; *scan
!= firstc
|| strncmp (scan
, wanted
, len
) != 0;)
1041 if (*scan
++ == '\0')
1046 #endif /* !HAVE_STRSTR */
1048 #ifndef HAVE_FTRUNCATE
1052 ftruncate (fd
, length
)
1056 return fcntl (fd
, F_CHSIZE
, length
);
1059 #else /* !F_CHSIZE */
1061 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
1064 ftruncate (fd
, length
)
1065 int fd
; /* file descriptor */
1066 off_t length
; /* length to set file to */
1072 fl
.l_start
= length
;
1073 fl
.l_type
= F_WRLCK
; /* write lock on file space */
1076 * This relies on the UNDOCUMENTED F_FREESP argument to
1077 * fcntl(2), which truncates the file so that it ends at the
1078 * position indicated by fl.l_start.
1080 * Will minor miracles never cease?
1083 if (fcntl (fd
, F_FREESP
, &fl
) < 0)
1089 #else /* !F_FREESP */
1092 ftruncate (fd
, length
)
1100 #endif /* !F_FREESP */
1101 #endif /* !F_CHSIZE */
1102 #endif /* !HAVE_FTRUNCATE */
1105 extern FILE *msg_file
;
1107 #if defined (HAVE_VPRINTF) && __STDC__
1115 va_start (args
, str
);
1117 fprintf (stderr
, "%s: ", tar
);
1119 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1120 vfprintf (stderr
, str
, args
);
1122 putc ('\n', stderr
);
1127 msg_perror (char *str
,...)
1134 fprintf (stderr
, "%s: ", tar
);
1136 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1137 va_start (args
, str
);
1138 vfprintf (stderr
, str
, args
);
1145 #endif /* HAVE_VPRINTF and __STDC__ */
1147 #if defined(HAVE_VPRINTF) && !__STDC__
1148 #include <varargs.h>
1157 fprintf (stderr
, "%s: ", tar
);
1159 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1161 vfprintf (stderr
, str
, args
);
1163 putc ('\n', stderr
);
1168 msg_perror (str
, va_alist
)
1177 fprintf (stderr
, "%s: ", tar
);
1179 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1181 vfprintf (stderr
, str
, args
);
1188 #endif /* HAVE_VPRINTF and not __STDC__ */
1190 #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
1197 fprintf (stderr
, "%s: ", tar
);
1199 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1200 _doprnt (str
, &args
, stderr
);
1201 putc ('\n', stderr
);
1206 msg_perror (str
, args
)
1214 fprintf (stderr
, "%s: ", tar
);
1216 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1217 _doprnt (str
, &args
, stderr
);
1223 #endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
1225 #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
1227 msg (str
, a1
, a2
, a3
, a4
, a5
, a6
)
1231 fprintf (stderr
, "%s: ", tar
);
1233 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1234 fprintf (stderr
, str
, a1
, a2
, a3
, a4
, a5
, a6
);
1235 putc ('\n', stderr
);
1240 msg_perror (str
, a1
, a2
, a3
, a4
, a5
, a6
)
1247 fprintf (stderr
, "%s: ", tar
);
1249 fprintf (stderr
, "rec %d: ", baserec
+ (ar_record
- ar_block
));
1250 fprintf (stderr
, str
, a1
, a2
, a3
, a4
, a5
, a6
);
1251 fprintf (stderr
, ": ");
1256 #endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
This page took 0.087436 seconds and 4 git commands to generate.