]>
Dogcows Code - chaz/tar/blob - src/port.c
1 /* Supporting routines which may sometimes be missing.
2 Copyright (C) 1988 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";
51 #define VALLOC_MISSING
53 #else /* not __MSDOS__ */
55 char TTY_NAME
[] ="/dev/tty";
58 #define CK_PIPE_MISSING
60 #endif /* not __MSDOS__ */
62 /* End of system-dependent #ifdefs */
67 * valloc() does a malloc() on a page boundary. On some systems,
68 * this can make large block I/O more efficient.
74 return (malloc (size
));
80 * Written by Robert Rother, Mariah Corporation, August 1985.
82 * If you want it, it's yours. All I ask in return is that if you
83 * figure out how to do this in a Bourne Shell script you send me
85 * sdcsvax!rmr or rmr@uscd
87 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
88 * subroutine. 11Mar86; hoptoad!gnu
90 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
91 * subroutine didn't return EEXIST. It does now.
105 if (stat(dpath
,&statbuf
) == 0) {
106 errno
= EEXIST
; /* Stat worked, so it already exists */
110 /* If stat fails for a reason other than non-existence, return error */
111 if (errno
!= ENOENT
) return -1;
113 switch (cpid
= fork()) {
115 case -1: /* Error in fork() */
116 return(-1); /* Errno is set already */
118 case 0: /* Child process */
120 * Cheap hack to set mode of new directory. Since this
121 * child process is going away anyway, we zap its umask.
122 * FIXME, this won't suffice to set SUID, SGID, etc. on this
123 * directory. Does anybody care?
125 status
= umask(0); /* Get current umask */
126 status
= umask(status
| (0777 & ~dmode
)); /* Set for mkdir */
127 execl("/bin/mkdir", "mkdir", dpath
, (char *)0);
128 _exit(-1); /* Can't exec /bin/mkdir */
130 default: /* Parent process */
131 while (cpid
!= wait(&status
)) ; /* Wait for kid to finish */
134 if (WTERMSIG(status
) != 0 || WEXITSTATUS(status
) != 0) {
135 errno
= EIO
; /* We don't know why, but */
136 return -1; /* /bin/mkdir failed */
149 if (stat(dpath
,&statbuf
) != 0) {
150 /* Stat just set errno. We don't have to */
154 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 (WTERMSIG(status
) != 0 || WEXITSTATUS(status
) != 0) {
168 errno
= EIO
; /* We don't know why, but */
169 return -1; /* /bin/mkdir failed */
176 #ifdef RENAME_MISSING
177 /* Rename file FROM to file TO.
178 Return 0 if successful, -1 if not. */
185 struct stat from_stats
;
187 if (stat (from
, &from_stats
) == 0)
189 if (unlink (to
) && errno
!= ENOENT
)
191 if (link (from
, to
) == 0 && (unlink (from
) == 0 || errno
== ENOENT
))
199 /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
205 while (n
--) *s1
++ = '\0';
208 /* It also has no bcmp() */
211 register char *s1
,*s2
;
214 for ( ; n
-- ; ++s1
, ++s2
) {
215 if (*s1
!= *s2
) return *s1
- *s2
;
221 * Groan, Minix doesn't have execlp either!
223 * execlp(file,arg0,arg1...argn,(char *)NULL)
224 * exec a program, automatically searching for the program through
225 * all the directories on the PATH.
227 * This version is naive about variable argument lists, it assumes
228 * a straightforward C calling sequence. If your system has odd stacks
229 * *and* doesn't have execlp, YOU get to fix it.
232 execlp(filename
, arg0
)
233 char *filename
, *arg0
;
235 register char *p
, *path
;
236 register char *fnbuffer
;
237 char **argstart
= &arg0
;
239 extern char **environ
;
241 if ((p
= getenv("PATH")) == NULL
) {
242 /* couldn't find path variable -- try to exec given filename */
243 return execve(filename
, argstart
, environ
);
247 * make a place to build the filename. We malloc larger than we
248 * need, but we know it will fit in this.
250 fnbuffer
= malloc( strlen(p
) + 1 + strlen(filename
) );
251 if (fnbuffer
== NULL
) {
257 * try each component of the path to see if the file's there
260 for (path
= p
; path
; path
= p
) {
261 /* construct full path name to try */
262 if ((p
= index(path
,':')) == NULL
) {
263 strcpy(fnbuffer
, path
);
265 strncpy(fnbuffer
, path
, p
-path
);
266 fnbuffer
[p
-path
] = '\0';
267 p
++; /* Skip : for next time */
269 if (strlen(fnbuffer
) != 0)
270 strcat(fnbuffer
,"/");
271 strcat(fnbuffer
,filename
);
273 /* check to see if file is there and is a normal file */
274 if (stat(fnbuffer
, &statbuf
) < 0) {
276 continue; /* file not there,keep on looking */
278 goto fail
; /* failed for some reason, return */
280 if (!S_ISREG(statbuf
.st_mode
)) continue;
282 if (execve(fnbuffer
, argstart
, environ
) < 0
284 && errno
!= ENOEXEC
) {
285 /* failed, for some other reason besides "file
286 * not found" or "not a.out format"
292 * If we got error ENOEXEC, the file is executable but is
293 * not an object file. Try to execute it as a shell script,
294 * returning error if we can't execute /bin/sh.
296 * FIXME, this code is broken in several ways. Shell
297 * scripts should not in general be executed by the user's
298 * SHELL variable program. On more mature systems, the
299 * script can specify with #!/bin/whatever. Also, this
300 * code clobbers argstart[-1] if the exec of the shell
303 if (errno
== ENOEXEC
) {
306 /* Try to execute command "sh arg0 arg1 ..." */
307 if ((shell
= getenv("SHELL")) == NULL
)
309 argstart
[-1] = shell
;
310 argstart
[0] = fnbuffer
;
311 execve(shell
, &argstart
[-1], environ
);
312 goto fail
; /* Exec didn't work */
316 * If we succeeded, the execve() doesn't return, so we
317 * can only be here is if the file hasn't been found yet.
318 * Try the next place on the path.
322 /* all attempts failed to locate the file. Give up. */
335 * open3 -- routine to emulate the 3-argument open system
336 * call that is present in most modern Unix systems.
337 * This version attempts to support all the flag bits except for O_NDELAY
338 * and O_APPEND, which are silently ignored. The emulation is not as efficient
339 * as the real thing (at worst, 4 system calls instead of one), but there's
340 * not much I can do about that.
342 * Written 6/10/87 by rmtodd@uokmax
344 * open3(path, flag, mode)
345 * Attempts to open the file specified by
346 * the given pathname. The following flag bits (#defined in tar.h)
347 * specify options to the routine:
348 * O_RDONLY file open for read only
349 * O_WRONLY file open for write only
350 * O_RDWR file open for both read & write
351 * (Needless to say, you should only specify one of the above).
352 * O_CREAT file is created with specified mode if it needs to be.
353 * O_TRUNC if file exists, it is truncated to 0 bytes
354 * O_EXCL used with O_CREAT--routine returns error if file exists
355 * Function returns file descriptor if successful, -1 and errno if not.
359 * array to give arguments to access for various modes
360 * FIXME, this table depends on the specific integer values of O_XXX,
361 * and also contains integers (args to 'access') that should be #define's.
368 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
371 /* Shut off the automatic emulation of open(), we'll need it. */
375 open3(path
, flags
, mode
)
383 * We actually do the work by calling the open() or creat() system
384 * call, depending on the flags. Call_creat is true if we will use
385 * creat(), false if we will use open().
389 * See if the file exists and is accessible in the requested mode.
391 * Strictly speaking we shouldn't be using access, since access checks
392 * against real uid, and the open call should check against euid.
393 * Most cases real uid == euid, so it won't matter. FIXME.
394 * FIXME, the construction "flags & 3" and the modes table depends
395 * on the specific integer values of the O_XXX #define's. Foo!
397 if (access(path
,modes
[flags
& 3]) < 0) {
398 if (errno
== ENOENT
) {
399 /* the file does not exist */
402 /* probably permission violation */
403 if (flags
& O_EXCL
) {
404 /* Oops, the file exists, we didn't want it. */
405 /* No matter what the error, claim EEXIST. */
412 /* if we have the O_CREAT bit set, check for O_EXCL */
413 if (flags
& O_CREAT
) {
414 if ((flags
& O_EXCL
) && exists
) {
415 /* Oops, the file exists and we didn't want it to. */
420 * If the file doesn't exist, be sure to call creat() so that
421 * it will be created with the proper mode.
423 if (!exists
) call_creat
= 1;
425 /* If O_CREAT isn't set and the file doesn't exist, error. */
433 * If the O_TRUNC flag is set and the file exists, we want to call
434 * creat() anyway, since creat() guarantees that the file will be
435 * truncated and open()-for-writing doesn't.
436 * (If the file doesn't exist, we're calling creat() anyway and the
437 * file will be created with zero length.)
439 if ((flags
& O_TRUNC
) && exists
) call_creat
= 1;
440 /* actually do the call */
443 * call creat. May have to close and reopen the file if we
444 * want O_RDONLY or O_RDWR access -- creat() only gives
447 fd
= creat(path
,mode
);
448 if (fd
< 0 || (flags
& O_WRONLY
)) return fd
;
449 if (close(fd
) < 0) return -1;
450 /* Fall out to reopen the file we've created */
454 * calling old open, we strip most of the new flags just in case.
456 return open(path
, flags
& (O_RDONLY
|O_WRONLY
|O_RDWR
|O_BINARY
));
464 /* Fake mknod by complaining */
466 mknod(path
, mode
, dev
)
473 errno
= ENXIO
; /* No such device or address */
474 return -1; /* Just give an error */
477 /* Fake links by copying */
488 fprintf(stderr
, "%s: %s: cannot link to %s, copying instead\n",
490 if ((ifd
= open(path1
, O_RDONLY
|O_BINARY
)) < 0)
492 if ((ofd
= creat(path2
, 0666)) < 0)
494 setmode(ofd
, O_BINARY
);
495 while ((nrbytes
= read(ifd
, buf
, sizeof(buf
))) > 0) {
496 if ((nwbytes
= write(ofd
, buf
, nrbytes
)) != nrbytes
) {
501 /* Note use of "|" rather than "||" below: we want to close
502 * the files even if an error occurs.
504 if ((nrbytes
< 0) | (0 != close(ifd
)) | (0 != close(ofd
))) {
511 /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
513 chown(path
, uid
, gid
)
526 #endif /* MKNOD_MISSING */
535 time_t actime
; /* Access time. */
536 time_t modtime
; /* Modification time. */
540 utime (char *filename
, struct utimbuf
*utb
)
543 struct ftime filetime
;
553 fd
= _open (filename
, O_RDWR
);
557 tm
= localtime (&when
);
558 if (tm
->tm_year
< 80)
559 filetime
.ft_year
= 0;
561 filetime
.ft_year
= tm
->tm_year
- 80;
562 filetime
.ft_month
= tm
->tm_mon
+ 1;
563 filetime
.ft_day
= tm
->tm_mday
;
565 filetime
.ft_hour
= 0;
567 filetime
.ft_hour
= tm
->tm_hour
;
568 filetime
.ft_min
= tm
->tm_min
;
569 filetime
.ft_tsec
= tm
->tm_sec
/ 2;
571 status
= setftime (fd
, &filetime
);
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
++;
930 #ifdef CK_PIPE_MISSING
935 msg_perror("can't open a pipe");
942 #ifdef STRSTR_MISSING
945 * strstr - find first occurrence of wanted in s
948 char * /* found string, or NULL if none */
955 register char firstc
;
960 * The odd placement of the two tests is so "" is findable.
961 * Also, we inline the first char for speed.
962 * The ++ on scan has been moved down for optimization.
965 len
= strlen(wanted
);
966 for (scan
= s
; *scan
!= firstc
|| strncmp(scan
, wanted
, len
) != 0; )
973 #ifdef FTRUNCATE_MISSING
977 ftruncate (fd
, length
)
981 return fcntl (fd
, F_CHSIZE
, length
);
985 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
988 ftruncate(fd
, length
)
989 int fd
; /* file descriptor */
990 off_t length
; /* length to set file to */
997 fl
.l_type
= F_WRLCK
; /* write lock on file space */
1000 * This relies on the UNDOCUMENTED F_FREESP argument to
1001 * fcntl(2), which truncates the file so that it ends at the
1002 * position indicated by fl.l_start.
1004 * Will minor miracles never cease?
1007 if (fcntl(fd
, F_FREESP
, &fl
) < 0)
1016 ftruncate(fd
, length
)
1028 extern FILE *msg_file
;
1030 #if !defined (VPRINTF_MISSING) && defined (__STDC__)
1040 fprintf(stderr
,"%s: ",tar
);
1042 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1043 vfprintf(stderr
,str
,args
);
1050 msg_perror(char *str
,...)
1057 fprintf(stderr
,"%s: ",tar
);
1059 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1061 vfprintf(stderr
,str
,args
);
1067 #endif /* not VPRINTF_MISSING or __STDC__ */
1069 #if !defined(VPRINTF_MISSING) && !defined(__STDC__)
1070 #include <varargs.h>
1079 fprintf(stderr
,"%s: ",tar
);
1081 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1083 vfprintf(stderr
,str
,args
);
1090 msg_perror(str
,va_alist
)
1099 fprintf(stderr
,"%s: ",tar
);
1101 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1103 vfprintf(stderr
,str
,args
);
1109 #endif /* not VPRINTF_MISSING and not __STDC__ */
1111 #if defined(VPRINTF_MISSING) && !defined(DOPRNT_MISSING)
1118 fprintf(stderr
,"%s: ",tar
);
1120 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1121 _doprnt(str
, &args
, stderr
);
1127 msg_perror(str
,args
)
1134 fprintf(stderr
,"%s: ",tar
);
1136 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1137 _doprnt(str
, &args
, stderr
);
1142 #endif /* VPRINTF_MISSING and not DOPRNT_MISSING */
1144 #if defined(VPRINTF_MISSING) && defined(DOPRNT_MISSING)
1145 void msg(str
,a1
,a2
,a3
,a4
,a5
,a6
)
1149 fprintf(stderr
,"%s: ",tar
);
1151 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1152 fprintf(stderr
,str
,a1
,a2
,a3
,a4
,a5
,a6
);
1158 msg_perror(str
,a1
,a2
,a3
,a4
,a5
,a6
)
1165 fprintf(stderr
,"%s: ",tar
);
1167 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1168 fprintf(stderr
,str
,a1
,a2
,a3
,a4
,a5
,a6
);
1169 fprintf(stderr
,": ");
1173 #endif /* VPRINTF_MISSING and DOPRNT_MISSING */
This page took 0.086039 seconds and 5 git commands to generate.