diff options
Diffstat (limited to 'gnu/libexec/uucp/libunix/trunc.c')
| -rw-r--r-- | gnu/libexec/uucp/libunix/trunc.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/trunc.c b/gnu/libexec/uucp/libunix/trunc.c new file mode 100644 index 000000000000..c93e82e39403 --- /dev/null +++ b/gnu/libexec/uucp/libunix/trunc.c @@ -0,0 +1,157 @@ +/* trunc.c + Truncate a file to zero length. */ + +#include "uucp.h" + +#include "uudefs.h" +#include "sysdep.h" +#include "system.h" + +#include <errno.h> + +#if HAVE_FCNTL_H +#include <fcntl.h> +#else +#if HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#endif + +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +/* External functions. */ +#ifndef lseek +extern off_t lseek (); +#endif + +/* Truncate a file to zero length. If this fails, it closes and + removes the file. We support a number of different means of + truncation, which is probably a waste of time since this function + is currently only called when the 'f' protocol resends a file. */ + +#if HAVE_FTRUNCATE +#undef HAVE_LTRUNC +#define HAVE_LTRUNC 0 +#endif + +#if ! HAVE_FTRUNCATE && ! HAVE_LTRUNC +#ifdef F_CHSIZE +#define HAVE_F_CHSIZE 1 +#else /* ! defined (F_CHSIZE) */ +#ifdef F_FREESP +#define HAVE_F_FREESP 1 +#endif /* defined (F_FREESP) */ +#endif /* ! defined (F_CHSIZE) */ +#endif /* ! HAVE_FTRUNCATE && ! HAVE_LTRUNC */ + +openfile_t +esysdep_truncate (e, zname) + openfile_t e; + const char *zname; +{ + int o; + +#if HAVE_FTRUNCATE || HAVE_LTRUNC || HAVE_F_CHSIZE || HAVE_F_FREESP + int itrunc; + + if (! ffilerewind (e)) + { + ulog (LOG_ERROR, "rewind: %s", strerror (errno)); + (void) ffileclose (e); + (void) remove (zname); + return EFILECLOSED; + } + +#if USE_STDIO + o = fileno (e); +#else + o = e; +#endif + +#if HAVE_FTRUNCATE + itrunc = ftruncate (o, 0); +#endif +#if HAVE_LTRUNC + itrunc = ltrunc (o, (long) 0, SEEK_SET); +#endif +#if HAVE_F_CHSIZE + itrunc = fcntl (o, F_CHSIZE, (off_t) 0); +#endif +#if HAVE_F_FREESP + /* This selection is based on an implementation of ftruncate by + kucharsk@Solbourne.com (William Kucharski). */ + { + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = 0; + fl.l_type = F_WRLCK; + + itrunc = fcntl (o, F_FREESP, &fl); + } +#endif + + if (itrunc != 0) + { +#if HAVE_FTRUNCATE + ulog (LOG_ERROR, "ftruncate: %s", strerror (errno)); +#endif +#ifdef HAVE_LTRUNC + ulog (LOG_ERROR, "ltrunc: %s", strerror (errno)); +#endif +#ifdef HAVE_F_CHSIZE + ulog (LOG_ERROR, "fcntl (F_CHSIZE): %s", strerror (errno)); +#endif +#ifdef HAVE_F_FREESP + ulog (LOG_ERROR, "fcntl (F_FREESP): %s", strerror (errno)); +#endif + + (void) ffileclose (e); + (void) remove (zname); + return EFILECLOSED; + } + + return e; +#else /* ! (HAVE_FTRUNCATE || HAVE_LTRUNC || HAVE_F_CHSIZE || HAVE_F_FREESP) */ + (void) ffileclose (e); + (void) remove (zname); + + o = creat ((char *) zname, IPRIVATE_FILE_MODE); + + if (o == -1) + { + ulog (LOG_ERROR, "creat (%s): %s", zname, strerror (errno)); + return EFILECLOSED; + } + + if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0) + { + ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); + (void) close (o); + return EFILECLOSED; + } + +#if USE_STDIO + e = fdopen (o, (char *) BINWRITE); + + if (e == NULL) + { + ulog (LOG_ERROR, "fdopen (%s): %s", zname, strerror (errno)); + (void) close (o); + (void) remove (zname); + return NULL; + } +#else /* ! USE_STDIO */ + e = o; +#endif /* ! USE_STDIO */ + + return e; +#endif /* ! (HAVE_FTRUNCATE || HAVE_LTRUNC || HAVE_F_CHSIZE || HAVE_F_FREESP) */ +} |
