]>
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";
49 #else /* not __MSDOS__ */
51 char TTY_NAME
[] ="/dev/tty";
53 #endif /* not __MSDOS__ */
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
));
69 #endif /* !HAVE_VALLOC */
73 * Written by Robert Rother, Mariah Corporation, August 1985.
75 * If you want it, it's yours. All I ask in return is that if you
76 * figure out how to do this in a Bourne Shell script you send me
78 * sdcsvax!rmr or rmr@uscd
80 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
81 * subroutine. 11Mar86; hoptoad!gnu
83 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
84 * subroutine didn't return EEXIST. It does now.
98 if (stat(dpath
,&statbuf
) == 0) {
99 errno
= EEXIST
; /* Stat worked, so it already exists */
103 /* If stat fails for a reason other than non-existence, return error */
104 if (errno
!= ENOENT
) return -1;
106 switch (cpid
= fork()) {
108 case -1: /* Error in fork() */
109 return(-1); /* Errno is set already */
111 case 0: /* Child process */
113 * Cheap hack to set mode of new directory. Since this
114 * child process is going away anyway, we zap its umask.
115 * FIXME, this won't suffice to set SUID, SGID, etc. on this
116 * directory. Does anybody care?
118 status
= umask(0); /* Get current umask */
119 status
= umask(status
| (0777 & ~dmode
)); /* Set for mkdir */
120 execl("/bin/mkdir", "mkdir", dpath
, (char *)0);
121 _exit(-1); /* Can't exec /bin/mkdir */
123 default: /* Parent process */
124 while (cpid
!= wait(&status
)) ; /* Wait for kid to finish */
127 if (WIFSIGNALED(status
) || WEXITSTATUS(status
) != 0) {
128 errno
= EIO
; /* We don't know why, but */
129 return -1; /* /bin/mkdir failed */
142 if (stat(dpath
,&statbuf
) != 0) {
143 /* Stat just set errno. We don't have to */
147 switch (cpid
= fork()) {
149 case -1: /* Error in fork() */
150 return(-1); /* Errno is set already */
152 case 0: /* Child process */
153 execl("/bin/rmdir", "rmdir", dpath
, (char *)0);
154 _exit(-1); /* Can't exec /bin/mkdir */
156 default: /* Parent process */
157 while (cpid
!= wait(&status
)) ; /* Wait for kid to finish */
160 if (WIFSIGNALED(status
) || WEXITSTATUS(status
) != 0) {
161 errno
= EIO
; /* We don't know why, but */
162 return -1; /* /bin/mkdir failed */
167 #endif /* !HAVE_MKDIR */
170 /* Rename file FROM to file TO.
171 Return 0 if successful, -1 if not. */
178 struct stat from_stats
;
180 if (stat (from
, &from_stats
))
183 if (unlink (to
) && errno
!= ENOENT
)
189 if (unlink (from
) && errno
!= ENOENT
)
197 #endif /* !HAVE_RENAME */
200 /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
206 while (n
--) *s1
++ = '\0';
209 /* It also has no bcmp() */
212 register char *s1
,*s2
;
215 for ( ; n
-- ; ++s1
, ++s2
) {
216 if (*s1
!= *s2
) return *s1
- *s2
;
222 * Groan, Minix doesn't have execlp either!
224 * execlp(file,arg0,arg1...argn,(char *)NULL)
225 * exec a program, automatically searching for the program through
226 * all the directories on the PATH.
228 * This version is naive about variable argument lists, it assumes
229 * a straightforward C calling sequence. If your system has odd stacks
230 * *and* doesn't have execlp, YOU get to fix it.
233 execlp(filename
, arg0
)
234 char *filename
, *arg0
;
236 register char *p
, *path
;
237 register char *fnbuffer
;
238 char **argstart
= &arg0
;
240 extern char **environ
;
242 if ((p
= getenv("PATH")) == NULL
) {
243 /* couldn't find path variable -- try to exec given filename */
244 return execve(filename
, argstart
, environ
);
248 * make a place to build the filename. We malloc larger than we
249 * need, but we know it will fit in this.
251 fnbuffer
= malloc( strlen(p
) + 1 + strlen(filename
) );
252 if (fnbuffer
== NULL
) {
258 * try each component of the path to see if the file's there
261 for (path
= p
; path
; path
= p
) {
262 /* construct full path name to try */
263 if ((p
= index(path
,':')) == NULL
) {
264 strcpy(fnbuffer
, path
);
266 strncpy(fnbuffer
, path
, p
-path
);
267 fnbuffer
[p
-path
] = '\0';
268 p
++; /* Skip : for next time */
270 if (strlen(fnbuffer
) != 0)
271 strcat(fnbuffer
,"/");
272 strcat(fnbuffer
,filename
);
274 /* check to see if file is there and is a normal file */
275 if (stat(fnbuffer
, &statbuf
) < 0) {
277 continue; /* file not there,keep on looking */
279 goto fail
; /* failed for some reason, return */
281 if (!S_ISREG(statbuf
.st_mode
)) continue;
283 if (execve(fnbuffer
, argstart
, environ
) < 0
285 && errno
!= ENOEXEC
) {
286 /* failed, for some other reason besides "file
287 * not found" or "not a.out format"
293 * If we got error ENOEXEC, the file is executable but is
294 * not an object file. Try to execute it as a shell script,
295 * returning error if we can't execute /bin/sh.
297 * FIXME, this code is broken in several ways. Shell
298 * scripts should not in general be executed by the user's
299 * SHELL variable program. On more mature systems, the
300 * script can specify with #!/bin/whatever. Also, this
301 * code clobbers argstart[-1] if the exec of the shell
304 if (errno
== ENOEXEC
) {
307 /* Try to execute command "sh arg0 arg1 ..." */
308 if ((shell
= getenv("SHELL")) == NULL
)
310 argstart
[-1] = shell
;
311 argstart
[0] = fnbuffer
;
312 execve(shell
, &argstart
[-1], environ
);
313 goto fail
; /* Exec didn't work */
317 * If we succeeded, the execve() doesn't return, so we
318 * can only be here is if the file hasn't been found yet.
319 * Try the next place on the path.
323 /* all attempts failed to locate the file. Give up. */
336 * open3 -- routine to emulate the 3-argument open system
337 * call that is present in most modern Unix systems.
338 * This version attempts to support all the flag bits except for O_NDELAY
339 * and O_APPEND, which are silently ignored. The emulation is not as efficient
340 * as the real thing (at worst, 4 system calls instead of one), but there's
341 * not much I can do about that.
343 * Written 6/10/87 by rmtodd@uokmax
345 * open3(path, flag, mode)
346 * Attempts to open the file specified by
347 * the given pathname. The following flag bits (#defined in tar.h)
348 * specify options to the routine:
349 * O_RDONLY file open for read only
350 * O_WRONLY file open for write only
351 * O_RDWR file open for both read & write
352 * (Needless to say, you should only specify one of the above).
353 * O_CREAT file is created with specified mode if it needs to be.
354 * O_TRUNC if file exists, it is truncated to 0 bytes
355 * O_EXCL used with O_CREAT--routine returns error if file exists
356 * Function returns file descriptor if successful, -1 and errno if not.
360 * array to give arguments to access for various modes
361 * FIXME, this table depends on the specific integer values of O_XXX,
362 * and also contains integers (args to 'access') that should be #define's.
369 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
372 /* Shut off the automatic emulation of open(), we'll need it. */
376 open3(path
, flags
, mode
)
384 * We actually do the work by calling the open() or creat() system
385 * call, depending on the flags. Call_creat is true if we will use
386 * creat(), false if we will use open().
390 * See if the file exists and is accessible in the requested mode.
392 * Strictly speaking we shouldn't be using access, since access checks
393 * against real uid, and the open call should check against euid.
394 * Most cases real uid == euid, so it won't matter. FIXME.
395 * FIXME, the construction "flags & 3" and the modes table depends
396 * on the specific integer values of the O_XXX #define's. Foo!
398 if (access(path
,modes
[flags
& 3]) < 0) {
399 if (errno
== ENOENT
) {
400 /* the file does not exist */
403 /* probably permission violation */
404 if (flags
& O_EXCL
) {
405 /* Oops, the file exists, we didn't want it. */
406 /* No matter what the error, claim EEXIST. */
413 /* if we have the O_CREAT bit set, check for O_EXCL */
414 if (flags
& O_CREAT
) {
415 if ((flags
& O_EXCL
) && exists
) {
416 /* Oops, the file exists and we didn't want it to. */
421 * If the file doesn't exist, be sure to call creat() so that
422 * it will be created with the proper mode.
424 if (!exists
) call_creat
= 1;
426 /* If O_CREAT isn't set and the file doesn't exist, error. */
434 * If the O_TRUNC flag is set and the file exists, we want to call
435 * creat() anyway, since creat() guarantees that the file will be
436 * truncated and open()-for-writing doesn't.
437 * (If the file doesn't exist, we're calling creat() anyway and the
438 * file will be created with zero length.)
440 if ((flags
& O_TRUNC
) && exists
) call_creat
= 1;
441 /* actually do the call */
444 * call creat. May have to close and reopen the file if we
445 * want O_RDONLY or O_RDWR access -- creat() only gives
448 fd
= creat(path
,mode
);
449 if (fd
< 0 || (flags
& O_WRONLY
)) return fd
;
450 if (close(fd
) < 0) return -1;
451 /* Fall out to reopen the file we've created */
455 * calling old open, we strip most of the new flags just in case.
457 return open(path
, flags
& (O_RDONLY
|O_WRONLY
|O_RDWR
|O_BINARY
));
459 #endif /* EMUL_OPEN3 */
465 /* Fake mknod by complaining */
467 mknod(path
, mode
, dev
)
474 errno
= ENXIO
; /* No such device or address */
475 return -1; /* Just give an error */
478 /* Fake links by copying */
489 fprintf(stderr
, "%s: %s: cannot link to %s, copying instead\n",
491 if ((ifd
= open(path1
, O_RDONLY
|O_BINARY
)) < 0)
493 if ((ofd
= creat(path2
, 0666)) < 0)
495 setmode(ofd
, O_BINARY
);
496 while ((nrbytes
= read(ifd
, buf
, sizeof(buf
))) > 0) {
497 if ((nwbytes
= write(ofd
, buf
, nrbytes
)) != nrbytes
) {
502 /* Note use of "|" rather than "||" below: we want to close
503 * the files even if an error occurs.
505 if ((nrbytes
< 0) | (0 != close(ifd
)) | (0 != close(ofd
))) {
512 /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
514 chown(path
, uid
, gid
)
527 #endif /* !HAVE_MKNOD */
536 time_t actime
; /* Access time. */
537 time_t modtime
; /* Modification time. */
541 utime (char *filename
, struct utimbuf
*utb
)
544 struct ftime filetime
;
554 fd
= _open (filename
, O_RDWR
);
558 tm
= localtime (&when
);
559 if (tm
->tm_year
< 80)
560 filetime
.ft_year
= 0;
562 filetime
.ft_year
= tm
->tm_year
- 80;
563 filetime
.ft_month
= tm
->tm_mon
+ 1;
564 filetime
.ft_day
= tm
->tm_mday
;
566 filetime
.ft_hour
= 0;
568 filetime
.ft_hour
= tm
->tm_hour
;
569 filetime
.ft_min
= tm
->tm_min
;
570 filetime
.ft_tsec
= tm
->tm_sec
/ 2;
572 status
= setftime (fd
, &filetime
);
576 #endif /* __TURBOC__ */
578 /* Stash argv[0] here so panic will know what the program is called */
586 fprintf(stderr
,"%s:",myname
);
603 panic("Couldn't allocate memory");
607 /* Used by alloca.c and bison.simple. */
612 return (char *) ck_malloc(size
);
625 ret
=realloc(ptr
,size
);
627 panic("Couldn't re-allocate memory");
631 /* Implement a variable sized buffer of 'stuff'. We don't know what it is,
632 nor do we care, as long as it doesn't mind being aligned on a char boundry.
641 #define MIN_ALLOCATE 50
648 b
=(struct buffer
*)ck_malloc(sizeof(struct buffer
));
649 b
->allocated
=MIN_ALLOCATE
;
650 b
->b
=(char *)ck_malloc(MIN_ALLOCATE
);
661 b
=(struct buffer
*)bb
;
677 b
=(struct buffer
*)bb
;
678 if(b
->length
+n
>b
->allocated
) {
679 b
->allocated
=b
->length
+n
+MIN_ALLOCATE
;
680 b
->b
=(char *)ck_realloc(b
->b
,b
->allocated
);
682 bcopy(p
,b
->b
+b
->length
,n
);
692 b
=(struct buffer
*)bb
;
697 merge_sort(list
,n
,off
,cmp
)
706 unsigned alength
,blength
;
711 #define NEXTOF(ptr) (* ((char **)(((char *)(ptr))+off) ) )
715 if((*cmp
)(list
,NEXTOF(list
))>0) {
726 for(tptr
=list
,tmp
=(n
-1)/2;tmp
;tptr
=NEXTOF(tptr
),tmp
--)
731 alist
=merge_sort(alist
,alength
,off
,cmp
);
732 blist
=merge_sort(blist
,blength
,off
,cmp
);
734 for(;alist
&& blist
;) {
735 if((*cmp
)(alist
,blist
)<0) {
738 prev
= &(NEXTOF(alist
));
743 prev
= &(NEXTOF(blist
));
760 msg_perror("can't close a file #%d",fd
);
767 /* Quote_copy_string is like quote_string, but instead of modifying the
768 string in place, it malloc-s a copy of the string, and returns that.
769 If the string does not have to be quoted, it returns the NULL string.
770 The allocated copy can, of course, be freed with free() after the
771 caller is done with it.
774 quote_copy_string(string
)
790 n
=(from_here
-string
)-1;
792 copy_buf
=(char *)malloc(n
+5+strlen(from_here
)*4);
795 bcopy(string
,copy_buf
,n
);
800 } else if(isprint(c
)) {
807 n
=(from_here
-string
)-1;
809 copy_buf
=(char *)malloc(n
+5+strlen(from_here
)*4);
812 bcopy(string
,copy_buf
,n
);
816 if(c
=='\n') *to_there
++='n';
817 else if(c
=='\t') *to_there
++='t';
818 else if(c
=='\f') *to_there
++='f';
819 else if(c
=='\b') *to_there
++='b';
820 else if(c
=='\r') *to_there
++='r';
821 else if(c
=='\177') *to_there
++='?';
823 to_there
[0]=(c
>>6)+'0';
824 to_there
[1]=((c
>>3)&07)+'0';
825 to_there
[2]=(c
&07)+'0';
838 /* Un_quote_string takes a quoted c-string (like those produced by
839 quote_string or quote_copy_string and turns it back into the
840 un-quoted original. This is done in place.
843 /* There is no un-quote-copy-string. Write it yourself */
846 un_quote_string(string
)
858 if(*from_here
!='\\') {
859 if(from_here
!=to_there
)
860 *to_there
++= *from_here
++;
862 from_here
++,to_there
++;
865 switch(*++from_here
) {
867 *to_there
++= *from_here
++;
901 tmp
= *from_here
- '0';
903 if(*from_here
<'0' || *from_here
>'7') {
907 tmp
= tmp
*8 + *from_here
-'0';
909 if(*from_here
<'0' || *from_here
>'7') {
913 tmp
=tmp
*8 + *from_here
-'0';
920 *to_there
++= *from_here
++;
933 msg_perror("can't open a pipe");
941 * strstr - find first occurrence of wanted in s
944 char * /* found string, or NULL if none */
951 register char firstc
;
956 * The odd placement of the two tests is so "" is findable.
957 * Also, we inline the first char for speed.
958 * The ++ on scan has been moved down for optimization.
961 len
= strlen(wanted
);
962 for (scan
= s
; *scan
!= firstc
|| strncmp(scan
, wanted
, len
) != 0; )
967 #endif /* !HAVE_STRSTR */
969 #ifndef HAVE_FTRUNCATE
973 ftruncate (fd
, length
)
977 return fcntl (fd
, F_CHSIZE
, length
);
979 #else /* !F_CHSIZE */
981 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
984 ftruncate(fd
, length
)
985 int fd
; /* file descriptor */
986 off_t length
; /* length to set file to */
993 fl
.l_type
= F_WRLCK
; /* write lock on file space */
996 * This relies on the UNDOCUMENTED F_FREESP argument to
997 * fcntl(2), which truncates the file so that it ends at the
998 * position indicated by fl.l_start.
1000 * Will minor miracles never cease?
1003 if (fcntl(fd
, F_FREESP
, &fl
) < 0)
1009 #else /* !F_FREESP */
1012 ftruncate(fd
, length
)
1019 #endif /* !F_FREESP */
1020 #endif /* !F_CHSIZE */
1021 #endif /* !HAVE_FTRUNCATE */
1024 extern FILE *msg_file
;
1026 #if defined (HAVE_VPRINTF) && __STDC__
1036 fprintf(stderr
,"%s: ",tar
);
1038 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1039 vfprintf(stderr
,str
,args
);
1046 msg_perror(char *str
,...)
1053 fprintf(stderr
,"%s: ",tar
);
1055 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1057 vfprintf(stderr
,str
,args
);
1063 #endif /* HAVE_VPRINTF and __STDC__ */
1065 #if defined(HAVE_VPRINTF) && !__STDC__
1066 #include <varargs.h>
1075 fprintf(stderr
,"%s: ",tar
);
1077 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1079 vfprintf(stderr
,str
,args
);
1086 msg_perror(str
,va_alist
)
1095 fprintf(stderr
,"%s: ",tar
);
1097 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1099 vfprintf(stderr
,str
,args
);
1105 #endif /* HAVE_VPRINTF and not __STDC__ */
1107 #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
1114 fprintf(stderr
,"%s: ",tar
);
1116 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1117 _doprnt(str
, &args
, stderr
);
1123 msg_perror(str
,args
)
1130 fprintf(stderr
,"%s: ",tar
);
1132 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1133 _doprnt(str
, &args
, stderr
);
1138 #endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
1140 #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
1141 void msg(str
,a1
,a2
,a3
,a4
,a5
,a6
)
1145 fprintf(stderr
,"%s: ",tar
);
1147 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1148 fprintf(stderr
,str
,a1
,a2
,a3
,a4
,a5
,a6
);
1154 msg_perror(str
,a1
,a2
,a3
,a4
,a5
,a6
)
1161 fprintf(stderr
,"%s: ",tar
);
1163 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1164 fprintf(stderr
,str
,a1
,a2
,a3
,a4
,a5
,a6
);
1165 fprintf(stderr
,": ");
1169 #endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
This page took 0.084654 seconds and 5 git commands to generate.