]>
Dogcows Code - chaz/tar/blob - src/port.c
2f3c28240aa6bc440688267497372446b0fea0fa
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";
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
));
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 (WTERMSIG(status
) != 0 || 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 (WTERMSIG(status
) != 0 || WEXITSTATUS(status
) != 0) {
161 errno
= EIO
; /* We don't know why, but */
162 return -1; /* /bin/mkdir failed */
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
) == 0)
182 if (unlink (to
) && errno
!= ENOENT
)
184 if (link (from
, to
) == 0 && (unlink (from
) == 0 || errno
== ENOENT
))
192 /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
198 while (n
--) *s1
++ = '\0';
201 /* It also has no bcmp() */
204 register char *s1
,*s2
;
207 for ( ; n
-- ; ++s1
, ++s2
) {
208 if (*s1
!= *s2
) return *s1
- *s2
;
214 * Groan, Minix doesn't have execlp either!
216 * execlp(file,arg0,arg1...argn,(char *)NULL)
217 * exec a program, automatically searching for the program through
218 * all the directories on the PATH.
220 * This version is naive about variable argument lists, it assumes
221 * a straightforward C calling sequence. If your system has odd stacks
222 * *and* doesn't have execlp, YOU get to fix it.
225 execlp(filename
, arg0
)
226 char *filename
, *arg0
;
228 register char *p
, *path
;
229 register char *fnbuffer
;
230 char **argstart
= &arg0
;
232 extern char **environ
;
234 if ((p
= getenv("PATH")) == NULL
) {
235 /* couldn't find path variable -- try to exec given filename */
236 return execve(filename
, argstart
, environ
);
240 * make a place to build the filename. We malloc larger than we
241 * need, but we know it will fit in this.
243 fnbuffer
= malloc( strlen(p
) + 1 + strlen(filename
) );
244 if (fnbuffer
== NULL
) {
250 * try each component of the path to see if the file's there
253 for (path
= p
; path
; path
= p
) {
254 /* construct full path name to try */
255 if ((p
= index(path
,':')) == NULL
) {
256 strcpy(fnbuffer
, path
);
258 strncpy(fnbuffer
, path
, p
-path
);
259 fnbuffer
[p
-path
] = '\0';
260 p
++; /* Skip : for next time */
262 if (strlen(fnbuffer
) != 0)
263 strcat(fnbuffer
,"/");
264 strcat(fnbuffer
,filename
);
266 /* check to see if file is there and is a normal file */
267 if (stat(fnbuffer
, &statbuf
) < 0) {
269 continue; /* file not there,keep on looking */
271 goto fail
; /* failed for some reason, return */
273 if (!S_ISREG(statbuf
.st_mode
)) continue;
275 if (execve(fnbuffer
, argstart
, environ
) < 0
277 && errno
!= ENOEXEC
) {
278 /* failed, for some other reason besides "file
279 * not found" or "not a.out format"
285 * If we got error ENOEXEC, the file is executable but is
286 * not an object file. Try to execute it as a shell script,
287 * returning error if we can't execute /bin/sh.
289 * FIXME, this code is broken in several ways. Shell
290 * scripts should not in general be executed by the user's
291 * SHELL variable program. On more mature systems, the
292 * script can specify with #!/bin/whatever. Also, this
293 * code clobbers argstart[-1] if the exec of the shell
296 if (errno
== ENOEXEC
) {
299 /* Try to execute command "sh arg0 arg1 ..." */
300 if ((shell
= getenv("SHELL")) == NULL
)
302 argstart
[-1] = shell
;
303 argstart
[0] = fnbuffer
;
304 execve(shell
, &argstart
[-1], environ
);
305 goto fail
; /* Exec didn't work */
309 * If we succeeded, the execve() doesn't return, so we
310 * can only be here is if the file hasn't been found yet.
311 * Try the next place on the path.
315 /* all attempts failed to locate the file. Give up. */
328 * open3 -- routine to emulate the 3-argument open system
329 * call that is present in most modern Unix systems.
330 * This version attempts to support all the flag bits except for O_NDELAY
331 * and O_APPEND, which are silently ignored. The emulation is not as efficient
332 * as the real thing (at worst, 4 system calls instead of one), but there's
333 * not much I can do about that.
335 * Written 6/10/87 by rmtodd@uokmax
337 * open3(path, flag, mode)
338 * Attempts to open the file specified by
339 * the given pathname. The following flag bits (#defined in tar.h)
340 * specify options to the routine:
341 * O_RDONLY file open for read only
342 * O_WRONLY file open for write only
343 * O_RDWR file open for both read & write
344 * (Needless to say, you should only specify one of the above).
345 * O_CREAT file is created with specified mode if it needs to be.
346 * O_TRUNC if file exists, it is truncated to 0 bytes
347 * O_EXCL used with O_CREAT--routine returns error if file exists
348 * Function returns file descriptor if successful, -1 and errno if not.
352 * array to give arguments to access for various modes
353 * FIXME, this table depends on the specific integer values of O_XXX,
354 * and also contains integers (args to 'access') that should be #define's.
361 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
364 /* Shut off the automatic emulation of open(), we'll need it. */
368 open3(path
, flags
, mode
)
376 * We actually do the work by calling the open() or creat() system
377 * call, depending on the flags. Call_creat is true if we will use
378 * creat(), false if we will use open().
382 * See if the file exists and is accessible in the requested mode.
384 * Strictly speaking we shouldn't be using access, since access checks
385 * against real uid, and the open call should check against euid.
386 * Most cases real uid == euid, so it won't matter. FIXME.
387 * FIXME, the construction "flags & 3" and the modes table depends
388 * on the specific integer values of the O_XXX #define's. Foo!
390 if (access(path
,modes
[flags
& 3]) < 0) {
391 if (errno
== ENOENT
) {
392 /* the file does not exist */
395 /* probably permission violation */
396 if (flags
& O_EXCL
) {
397 /* Oops, the file exists, we didn't want it. */
398 /* No matter what the error, claim EEXIST. */
405 /* if we have the O_CREAT bit set, check for O_EXCL */
406 if (flags
& O_CREAT
) {
407 if ((flags
& O_EXCL
) && exists
) {
408 /* Oops, the file exists and we didn't want it to. */
413 * If the file doesn't exist, be sure to call creat() so that
414 * it will be created with the proper mode.
416 if (!exists
) call_creat
= 1;
418 /* If O_CREAT isn't set and the file doesn't exist, error. */
426 * If the O_TRUNC flag is set and the file exists, we want to call
427 * creat() anyway, since creat() guarantees that the file will be
428 * truncated and open()-for-writing doesn't.
429 * (If the file doesn't exist, we're calling creat() anyway and the
430 * file will be created with zero length.)
432 if ((flags
& O_TRUNC
) && exists
) call_creat
= 1;
433 /* actually do the call */
436 * call creat. May have to close and reopen the file if we
437 * want O_RDONLY or O_RDWR access -- creat() only gives
440 fd
= creat(path
,mode
);
441 if (fd
< 0 || (flags
& O_WRONLY
)) return fd
;
442 if (close(fd
) < 0) return -1;
443 /* Fall out to reopen the file we've created */
447 * calling old open, we strip most of the new flags just in case.
449 return open(path
, flags
& (O_RDONLY
|O_WRONLY
|O_RDWR
|O_BINARY
));
457 /* Fake mknod by complaining */
459 mknod(path
, mode
, dev
)
466 errno
= ENXIO
; /* No such device or address */
467 return -1; /* Just give an error */
470 /* Fake links by copying */
481 fprintf(stderr
, "%s: %s: cannot link to %s, copying instead\n",
483 if ((ifd
= open(path1
, O_RDONLY
|O_BINARY
)) < 0)
485 if ((ofd
= creat(path2
, 0666)) < 0)
487 setmode(ofd
, O_BINARY
);
488 while ((nrbytes
= read(ifd
, buf
, sizeof(buf
))) > 0) {
489 if ((nwbytes
= write(ofd
, buf
, nrbytes
)) != nrbytes
) {
494 /* Note use of "|" rather than "||" below: we want to close
495 * the files even if an error occurs.
497 if ((nrbytes
< 0) | (0 != close(ifd
)) | (0 != close(ofd
))) {
504 /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
506 chown(path
, uid
, gid
)
519 #endif /* !HAVE_MKNOD */
528 time_t actime
; /* Access time. */
529 time_t modtime
; /* Modification time. */
533 utime (char *filename
, struct utimbuf
*utb
)
536 struct ftime filetime
;
546 fd
= _open (filename
, O_RDWR
);
550 tm
= localtime (&when
);
551 if (tm
->tm_year
< 80)
552 filetime
.ft_year
= 0;
554 filetime
.ft_year
= tm
->tm_year
- 80;
555 filetime
.ft_month
= tm
->tm_mon
+ 1;
556 filetime
.ft_day
= tm
->tm_mday
;
558 filetime
.ft_hour
= 0;
560 filetime
.ft_hour
= tm
->tm_hour
;
561 filetime
.ft_min
= tm
->tm_min
;
562 filetime
.ft_tsec
= tm
->tm_sec
/ 2;
564 status
= setftime (fd
, &filetime
);
570 /* Stash argv[0] here so panic will know what the program is called */
578 fprintf(stderr
,"%s:",myname
);
595 panic("Couldn't allocate memory");
599 /* Used by alloca.c and bison.simple. */
604 return (char *) ck_malloc(size
);
617 ret
=realloc(ptr
,size
);
619 panic("Couldn't re-allocate memory");
623 /* Implement a variable sized buffer of 'stuff'. We don't know what it is,
624 nor do we care, as long as it doesn't mind being aligned on a char boundry.
633 #define MIN_ALLOCATE 50
640 b
=(struct buffer
*)ck_malloc(sizeof(struct buffer
));
641 b
->allocated
=MIN_ALLOCATE
;
642 b
->b
=(char *)ck_malloc(MIN_ALLOCATE
);
653 b
=(struct buffer
*)bb
;
669 b
=(struct buffer
*)bb
;
670 if(b
->length
+n
>b
->allocated
) {
671 b
->allocated
=b
->length
+n
+MIN_ALLOCATE
;
672 b
->b
=(char *)ck_realloc(b
->b
,b
->allocated
);
674 bcopy(p
,b
->b
+b
->length
,n
);
684 b
=(struct buffer
*)bb
;
689 merge_sort(list
,n
,off
,cmp
)
698 unsigned alength
,blength
;
703 #define NEXTOF(ptr) (* ((char **)(((char *)(ptr))+off) ) )
707 if((*cmp
)(list
,NEXTOF(list
))>0) {
718 for(tptr
=list
,tmp
=(n
-1)/2;tmp
;tptr
=NEXTOF(tptr
),tmp
--)
723 alist
=merge_sort(alist
,alength
,off
,cmp
);
724 blist
=merge_sort(blist
,blength
,off
,cmp
);
726 for(;alist
&& blist
;) {
727 if((*cmp
)(alist
,blist
)<0) {
730 prev
= &(NEXTOF(alist
));
735 prev
= &(NEXTOF(blist
));
752 msg_perror("can't close a file #%d",fd
);
759 /* Quote_copy_string is like quote_string, but instead of modifying the
760 string in place, it malloc-s a copy of the string, and returns that.
761 If the string does not have to be quoted, it returns the NULL string.
762 The allocated copy can, of course, be freed with free() after the
763 caller is done with it.
766 quote_copy_string(string
)
782 n
=(from_here
-string
)-1;
784 copy_buf
=(char *)malloc(n
+5+strlen(from_here
)*4);
787 bcopy(string
,copy_buf
,n
);
792 } else if(isprint(c
)) {
799 n
=(from_here
-string
)-1;
801 copy_buf
=(char *)malloc(n
+5+strlen(from_here
)*4);
804 bcopy(string
,copy_buf
,n
);
808 if(c
=='\n') *to_there
++='n';
809 else if(c
=='\t') *to_there
++='t';
810 else if(c
=='\f') *to_there
++='f';
811 else if(c
=='\b') *to_there
++='b';
812 else if(c
=='\r') *to_there
++='r';
813 else if(c
=='\177') *to_there
++='?';
815 to_there
[0]=(c
>>6)+'0';
816 to_there
[1]=((c
>>3)&07)+'0';
817 to_there
[2]=(c
&07)+'0';
830 /* Un_quote_string takes a quoted c-string (like those produced by
831 quote_string or quote_copy_string and turns it back into the
832 un-quoted original. This is done in place.
835 /* There is no un-quote-copy-string. Write it yourself */
838 un_quote_string(string
)
850 if(*from_here
!='\\') {
851 if(from_here
!=to_there
)
852 *to_there
++= *from_here
++;
854 from_here
++,to_there
++;
857 switch(*++from_here
) {
859 *to_there
++= *from_here
++;
893 tmp
= *from_here
- '0';
895 if(*from_here
<'0' || *from_here
>'7') {
899 tmp
= tmp
*8 + *from_here
-'0';
901 if(*from_here
<'0' || *from_here
>'7') {
905 tmp
=tmp
*8 + *from_here
-'0';
912 *to_there
++= *from_here
++;
925 msg_perror("can't open a pipe");
933 * strstr - find first occurrence of wanted in s
936 char * /* found string, or NULL if none */
943 register char firstc
;
948 * The odd placement of the two tests is so "" is findable.
949 * Also, we inline the first char for speed.
950 * The ++ on scan has been moved down for optimization.
953 len
= strlen(wanted
);
954 for (scan
= s
; *scan
!= firstc
|| strncmp(scan
, wanted
, len
) != 0; )
961 #infdef HAVE_FTRUNCATE
965 ftruncate (fd
, length
)
969 return fcntl (fd
, F_CHSIZE
, length
);
973 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
976 ftruncate(fd
, length
)
977 int fd
; /* file descriptor */
978 off_t length
; /* length to set file to */
985 fl
.l_type
= F_WRLCK
; /* write lock on file space */
988 * This relies on the UNDOCUMENTED F_FREESP argument to
989 * fcntl(2), which truncates the file so that it ends at the
990 * position indicated by fl.l_start.
992 * Will minor miracles never cease?
995 if (fcntl(fd
, F_FREESP
, &fl
) < 0)
1004 ftruncate(fd
, length
)
1016 extern FILE *msg_file
;
1018 #if defined (HAVE_VPRINTF) && __STDC__
1028 fprintf(stderr
,"%s: ",tar
);
1030 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1031 vfprintf(stderr
,str
,args
);
1038 msg_perror(char *str
,...)
1045 fprintf(stderr
,"%s: ",tar
);
1047 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1049 vfprintf(stderr
,str
,args
);
1055 #endif /* HAVE_VPRINTF and __STDC__ */
1057 #if defined(HAVE_VPRINTF) && !__STDC__
1058 #include <varargs.h>
1067 fprintf(stderr
,"%s: ",tar
);
1069 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1071 vfprintf(stderr
,str
,args
);
1078 msg_perror(str
,va_alist
)
1087 fprintf(stderr
,"%s: ",tar
);
1089 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1091 vfprintf(stderr
,str
,args
);
1097 #endif /* HAVE_VPRINTF and not __STDC__ */
1099 #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
1106 fprintf(stderr
,"%s: ",tar
);
1108 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1109 _doprnt(str
, &args
, stderr
);
1115 msg_perror(str
,args
)
1122 fprintf(stderr
,"%s: ",tar
);
1124 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1125 _doprnt(str
, &args
, stderr
);
1130 #endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
1132 #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
1133 void msg(str
,a1
,a2
,a3
,a4
,a5
,a6
)
1137 fprintf(stderr
,"%s: ",tar
);
1139 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1140 fprintf(stderr
,str
,a1
,a2
,a3
,a4
,a5
,a6
);
1146 msg_perror(str
,a1
,a2
,a3
,a4
,a5
,a6
)
1153 fprintf(stderr
,"%s: ",tar
);
1155 fprintf(stderr
,"rec %d: ",baserec
+ (ar_record
- ar_block
));
1156 fprintf(stderr
,str
,a1
,a2
,a3
,a4
,a5
,a6
);
1157 fprintf(stderr
,": ");
1161 #endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
This page took 0.081953 seconds and 4 git commands to generate.