1/* trunc.c 2 Truncate a file to zero length. */ 3 4#include "uucp.h" 5 6#include "uudefs.h" 7#include "sysdep.h" 8#include "system.h" 9 10#include <errno.h> 11 12#if HAVE_FCNTL_H 13#include <fcntl.h> 14#else 15#if HAVE_SYS_FILE_H 16#include <sys/file.h> 17#endif 18#endif 19 20#ifndef FD_CLOEXEC 21#define FD_CLOEXEC 1 22#endif 23 24#ifndef SEEK_SET 25#define SEEK_SET 0 26#endif 27 28/* External functions. */ 29#ifndef lseek 30extern off_t lseek (); 31#endif 32 33/* Truncate a file to zero length. If this fails, it closes and 34 removes the file. We support a number of different means of 35 truncation, which is probably a waste of time since this function 36 is currently only called when the 'f' protocol resends a file. */ 37 38#if HAVE_FTRUNCATE 39#undef HAVE_LTRUNC 40#define HAVE_LTRUNC 0 41#endif 42 43#if ! HAVE_FTRUNCATE && ! HAVE_LTRUNC 44#ifdef F_CHSIZE 45#define HAVE_F_CHSIZE 1 46#else /* ! defined (F_CHSIZE) */ 47#ifdef F_FREESP 48#define HAVE_F_FREESP 1 49#endif /* defined (F_FREESP) */ 50#endif /* ! defined (F_CHSIZE) */ 51#endif /* ! HAVE_FTRUNCATE && ! HAVE_LTRUNC */ 52 53openfile_t 54esysdep_truncate (e, zname) 55 openfile_t e; 56 const char *zname; 57{ 58 int o; 59 60#if HAVE_FTRUNCATE || HAVE_LTRUNC || HAVE_F_CHSIZE || HAVE_F_FREESP 61 int itrunc; 62 63 if (! ffilerewind (e)) 64 { 65 ulog (LOG_ERROR, "rewind: %s", strerror (errno)); 66 (void) ffileclose (e); 67 (void) remove (zname); 68 return EFILECLOSED; 69 } 70 71#if USE_STDIO 72 o = fileno (e); 73#else 74 o = e; 75#endif 76 77#if HAVE_FTRUNCATE 78 itrunc = ftruncate (o, 0); 79#endif 80#if HAVE_LTRUNC 81 itrunc = ltrunc (o, (long) 0, SEEK_SET); 82#endif 83#if HAVE_F_CHSIZE 84 itrunc = fcntl (o, F_CHSIZE, (off_t) 0); 85#endif 86#if HAVE_F_FREESP 87 /* This selection is based on an implementation of ftruncate by 88 kucharsk@Solbourne.com (William Kucharski). */ 89 { 90 struct flock fl; 91 92 fl.l_whence = 0; 93 fl.l_len = 0; 94 fl.l_start = 0; 95 fl.l_type = F_WRLCK; 96 97 itrunc = fcntl (o, F_FREESP, &fl); 98 } 99#endif 100 101 if (itrunc != 0) 102 { 103#if HAVE_FTRUNCATE 104 ulog (LOG_ERROR, "ftruncate: %s", strerror (errno)); 105#endif 106#ifdef HAVE_LTRUNC 107 ulog (LOG_ERROR, "ltrunc: %s", strerror (errno)); 108#endif 109#ifdef HAVE_F_CHSIZE 110 ulog (LOG_ERROR, "fcntl (F_CHSIZE): %s", strerror (errno)); 111#endif 112#ifdef HAVE_F_FREESP 113 ulog (LOG_ERROR, "fcntl (F_FREESP): %s", strerror (errno)); 114#endif 115 116 (void) ffileclose (e); 117 (void) remove (zname); 118 return EFILECLOSED; 119 } 120 121 return e; 122#else /* ! (HAVE_FTRUNCATE || HAVE_LTRUNC || HAVE_F_CHSIZE || HAVE_F_FREESP) */ 123 (void) ffileclose (e); 124 (void) remove (zname); 125 126 o = creat ((char *) zname, IPRIVATE_FILE_MODE); 127 128 if (o == -1) 129 { 130 ulog (LOG_ERROR, "creat during esysdep_truncate (%s): %s", zname, strerror (errno)); 131 return EFILECLOSED; 132 } 133 134 if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0) 135 { 136 ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); 137 (void) close (o); 138 return EFILECLOSED; 139 } 140 141#if USE_STDIO 142 e = fdopen (o, (char *) BINWRITE); 143 144 if (e == NULL) 145 { 146 ulog (LOG_ERROR, "fdopen (%s): %s", zname, strerror (errno)); 147 (void) close (o); 148 (void) remove (zname); 149 return NULL; 150 } 151#else /* ! USE_STDIO */ 152 e = o; 153#endif /* ! USE_STDIO */ 154 155 return e; 156#endif /* ! (HAVE_FTRUNCATE || HAVE_LTRUNC || HAVE_F_CHSIZE || HAVE_F_FREESP) */ 157} 158