summaryrefslogtreecommitdiffstats
path: root/gnu/libexec/uucp/libunix/trunc.c
blob: c93e82e394038b6fb79967897d4c53c6517c6ec6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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) */
}
OpenPOWER on IntegriCloud