/* Low Level Interface Library Copyright 1983-2008 Green Hills Software,Inc. * This program is the property of Green Hills Software, Inc, * its contents are proprietary information and no part of it * is to be disclosed to anyone except employees of Green Hills * Software, Inc., or as agreed in writing signed by the President * of Green Hills Software, Inc. */ /* ind_trnc.c: NON-ANSI truncate() facility. Provided for FORTRAN support. */ #include "indos.h" #include "ind_io.h" #if !defined(ANYBSD) && !defined(ANYSYSV4) #if defined(__VXWORKS) #include #include #else #ifndef L_tmpnam #define L_tmpnam 32 #endif #ifdef TMPNAMPREFIX # define L_TMPNAMEPREFIX 0 #elif defined(ANYUNIX)||defined(UNIXSYSCALLS)||defined(vms)||defined(__vms) # define TMPNAMPREFIX "gh_" # define L_TMPNAMEPREFIX 3 #else # define TMPNAMPREFIX "T" # define L_TMPNAMEPREFIX 1 #endif /* access is better everywhere */ #define USE_ACCESS #ifndef USE_ACESS int stat(char *, struct stat *); #endif static char *tmpnam(char *s) { /******************************************************************************/ /* This static tmpnam function is only needed for truncate, which is */ /* only needed if the Green Hills Fortran Library is being used. */ /* There is an exact copy of this function in the Green Hills C library. */ /******************************************************************************/ #pragma ghs nowarning 1908 static const char hexmap[32]="0123456789abcdefghijklmnopqrstuv"; #pragma ghs endnowarning int cnt = 0; int chan, u=17; char *p, *q; #ifdef TMPNAMPREFIX /* if (sizeof(space) < (sizeof(TMPNAMPREFIX) + 8)) */ /* return NULL; */ #elif defined(ANYUNIX)||defined(UNIXSYSCALLS)||defined(vms)||defined(__vms) #else #endif #if L_tmpnam < L_TMPNAMEPREFIX + 8 # error L_tmpnam too small #endif #if defined(ANYUNIX) || defined(UNIXSYSCALLS) || defined(MSW) u = getpid(); #endif /* if ( s==NULL ) */ /* s=space; */ for (p = s, q = TMPNAMPREFIX; *q; ) *p++ = *q++; #if defined(ANYUNIX) || defined(UNIXSYSCALLS) || defined(MSW) *p++ = hexmap[(u>>10) & 31]; *p++ = hexmap[(u>>5) & 31]; *p++ = hexmap[u & 31]; #endif #ifndef USE_ACCESS olderrno = __gh_get_errno(); /* access does not mess with errno */ #endif do { char *qq = p; u = (++cnt & 0x0fffff); do { *qq++ = hexmap[u & 31]; u >>= 5; } while (u); *qq = '\0'; #ifdef USE_ACESS chan = access(s, F_OK); #else { struct stat st; chan = stat(s, &st); } #endif } while ( chan!=-1 ); #ifndef USE_ACCESS __gh_set_errno(olderrno); #endif return(s); } #endif /* defined(__VXWORKS) */ /******************************************************************************/ /* The Green Hills C Library does not use the truncate function, it is only */ /* needed if the Green Hills Fortran Library is being used. */ /* */ /* int truncate(const char *path, int length); */ /* */ /* If the file named "path" is longer than "length" bytes it is truncated */ /* to "length" bytes. */ /* */ /* Return 0 if the named file is truncated or was previously less than */ /* length bytes. Return -1 if the file cannot be truncated, and set */ /* errno appropriately. */ /* */ /* REENTRANT */ /******************************************************************************/ #define _0777 0x1ff #if defined(__VXWORKS) #define __CREAT_ARG O_WRONLY #else #define __CREAT_ARG _0777 #endif #define LBUFSIZ 1024 int truncate(const char *path, long length) { /* The following implementation copies the first "length" bytes of the file named "path" to a temporary file, then it creates a new file with the name "path" and copies the temporary file back into it. At the end the temporary file is deleted. The prefered implementation is to shorten the file without copying, but many operating systems lack such an operation. */ char buf[LBUFSIZ]; char namebuff[L_tmpnam]; int inf, of; int count = 0; char *tmpname = tmpnam(namebuff); /* handle the two trivial cases efficiently: length is 0 and length is greater than or equal to actual size of file */ if (length == 0) { if ((of = creat(path, __CREAT_ARG)) == -1) return -1; close(of); return 0; } #if !defined(CROSSUNIX) && \ (defined(ANYUNIX)||defined(UNIXSYSCALLS)||defined(MSW)||defined(__VXWORKS)) { struct stat stat1; if (stat((char *)path, &stat1) < 0) return -1; if (stat1.st_size != (unsigned long)-1 && length >= stat1.st_size) return 0; } #endif if ((inf = open(path, 0, 0)) == -1 || (of = creat(tmpname, __CREAT_ARG)) == -1) { if (inf != -1) close(inf); return(-1); } while (length > 0 && (count = read(inf, buf, LBUFSIZ)) > 0) { if (count > length) count = length; if (count > write(of, buf, count)) { count = -1; break; } length -= count; } close(inf); close(of); if (length == 0 && count >= 0) { if (rename(tmpname, path) == 0) { return(0); } #if defined(vms) || defined(__vms) delete(path); #elif defined (__VXWORKS) { char *tmp_path = malloc (strlen(path) + 1); if (tmp_path == NULL) return -1; strcpy (tmp_path, path); unlink(tmp_path); free (tmp_path); } #else unlink(path); #endif if (rename(tmpname, path) == 0) { return(0); } if ((inf = open(tmpname, 0, 0)) == -1 || (of = creat(path, _0777)) == -1) { if (inf != -1) close(inf); return(-1); } while ((count = read(inf, buf, LBUFSIZ)) > 0) if (count > write(of, buf, count)) { count = -1; break; } close(inf); close(of); } #if defined(vms) || defined(__vms) delete(tmpname); #else unlink(tmpname); #endif return(count); } #else int _M_empty_file_illegal; #endif /* ! ANYBSD */