1/* copy.c
2   Copy one file to another for the UUCP package.
3
4   Copyright (C) 1991, 1992, 1995, 2002 Ian Lance Taylor
5
6   This file is part of the Taylor UUCP package.
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21
22   The author of the program may be contacted at ian@airs.com.
23   */
24
25#include "uucp.h"
26
27#if USE_RCS_ID
28const char copy_rcsid[] = "$Id: copy.c,v 1.22 2002/03/05 19:10:41 ian Rel $";
29#endif
30
31#include "uudefs.h"
32#include "system.h"
33#include "sysdep.h"
34
35#include <stdio.h>
36#include <errno.h>
37
38/* Copy one file to another.  */
39
40#if USE_STDIO
41
42boolean
43fcopy_file (zfrom, zto, fpublic, fmkdirs, fsignals)
44     const char *zfrom;
45     const char *zto;
46     boolean fpublic;
47     boolean fmkdirs;
48     boolean fsignals;
49{
50  FILE *efrom;
51  boolean fret;
52
53  efrom = fopen (zfrom, BINREAD);
54  if (efrom == NULL)
55    {
56      ulog (LOG_ERROR, "fopen (%s): %s", zfrom, strerror (errno));
57      return FALSE;
58    }
59
60  fret = fcopy_open_file (efrom, zto, fpublic, fmkdirs, fsignals);
61  (void) fclose (efrom);
62  return fret;
63}
64
65boolean
66fcopy_open_file (efrom, zto, fpublic, fmkdirs, fsignals)
67     FILE *efrom;
68     const char *zto;
69     boolean fpublic;
70     boolean fmkdirs;
71     boolean fsignals;
72{
73  FILE *eto;
74  char ab[8192];
75  size_t c;
76
77  eto = esysdep_fopen (zto, fpublic, FALSE, fmkdirs);
78  if (eto == NULL)
79    return FALSE;
80
81  while ((c = fread (ab, sizeof (char), sizeof ab, efrom)) != 0)
82    {
83      if (fwrite (ab, sizeof (char), (size_t) c, eto) != c)
84	{
85	  ulog (LOG_ERROR, "fwrite: %s", strerror (errno));
86	  (void) fclose (eto);
87	  (void) remove (zto);
88	  return FALSE;
89	}
90      if (fsignals && FGOT_SIGNAL ())
91	{
92	  /* Log the signal.  */
93	  ulog (LOG_ERROR, (const char *) NULL);
94	  (void) fclose (eto);
95	  (void) remove (zto);
96	  return FALSE;
97	}
98    }
99
100  if (! fsysdep_sync (eto, zto))
101    {
102      (void) fclose (eto);
103      (void) remove (zto);
104      return FALSE;
105    }
106
107  if (fclose (eto) != 0)
108    {
109      ulog (LOG_ERROR, "fclose: %s", strerror (errno));
110      (void) remove (zto);
111      return FALSE;
112    }
113
114  if (ferror (efrom))
115    {
116      ulog (LOG_ERROR, "fread: %s", strerror (errno));
117      (void) remove (zto);
118      return FALSE;
119    }
120
121  return TRUE;
122}
123
124#else /* ! USE_STDIO */
125
126#if HAVE_FCNTL_H
127#include <fcntl.h>
128#else
129#if HAVE_SYS_FILE_H
130#include <sys/file.h>
131#endif
132#endif
133
134#ifndef O_RDONLY
135#define O_RDONLY 0
136#define O_WRONLY 1
137#define O_RDWR 2
138#endif
139
140#ifndef O_NOCTTY
141#define O_NOCTTY 0
142#endif
143
144boolean
145fcopy_file (zfrom, zto, fpublic, fmkdirs, fsignals)
146     const char *zfrom;
147     const char *zto;
148     boolean fpublic;
149     boolean fmkdirs;
150     boolean fsignals;
151{
152  int ofrom;
153  boolean fret;
154
155  ofrom = open (zfrom, O_RDONLY | O_NOCTTY, 0);
156  if (ofrom < 0)
157    {
158      ulog (LOG_ERROR, "open (%s): %s", zfrom, strerror (errno));
159      return FALSE;
160    }
161
162  fret = fcopy_open_file (ofrom, zto, fpublic, fmkdirs, fsignals);
163  (void) close (ofrom);
164  return fret;
165}
166
167boolean
168fcopy_open_file (ofrom, zto, fpublic, fmkdirs, fsignals)
169     int ofrom;
170     const char *zto;
171     boolean fpublic;
172     boolean fmkdirs;
173     boolean fsignals;
174{
175  int oto;
176  char ab[8192];
177  int c;
178
179  /* These file mode arguments are from the UNIX version of sysdep.h;
180     each system dependent header file will need their own
181     definitions.  */
182  oto = creat (zto, fpublic ? IPUBLIC_FILE_MODE : IPRIVATE_FILE_MODE);
183  if (oto < 0)
184    {
185      if (errno == ENOENT && fmkdirs)
186	{
187	  if (! fsysdep_make_dirs (zto, fpublic))
188	    return FALSE;
189	  oto = creat (zto,
190		       fpublic ? IPUBLIC_FILE_MODE : IPRIVATE_FILE_MODE);
191	}
192      if (oto < 0)
193	{
194	  ulog (LOG_ERROR, "open (%s): %s", zto, strerror (errno));
195	  return FALSE;
196	}
197    }
198
199  while ((c = read (ofrom, ab, sizeof ab)) > 0)
200    {
201      if (write (oto, ab, (size_t) c) != c)
202	{
203	  ulog (LOG_ERROR, "write: %s", strerror (errno));
204	  (void) close (oto);
205	  (void) remove (zto);
206	  return FALSE;
207	}
208      if (fsignals && FGOT_SIGNAL ())
209	{
210	  /* Log the signal.  */
211	  ulog (LOG_ERROR, (const char *) NULL);
212	  (void) fclose (eto);
213	  (void) remove (zto);
214	  return FALSE;
215	}
216    }
217
218  if (! fsysdep_sync (oto, zto))
219    {
220      (void) close (oto);
221      (void) remove (zto);
222      return FALSE;
223    }
224
225  if (close (oto) < 0)
226    {
227      ulog (LOG_ERROR, "close: %s", strerror (errno));
228      (void) remove (zto);
229      return FALSE;
230    }
231
232  if (c < 0)
233    {
234      ulog (LOG_ERROR, "read: %s", strerror (errno));
235      (void) remove (zto);
236      return FALSE;
237    }
238
239  return TRUE;
240}
241
242#endif /* ! USE_STDIO */
243