1 //
2 // aegis - project change supervisor
3 // Copyright (C) 2001-2006, 2008 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19
20 #include <common/ac/errno.h>
21 #include <common/ac/fcntl.h>
22 #include <common/ac/stdlib.h>
23 #include <common/ac/unistd.h>
24
25 #include <libaegis/glue.h>
26 #include <libaegis/os.h>
27 #include <common/trace.h>
28
29
30 //
31 // NAME
32 // copyfile - copy a file
33 //
34 // SYNOPSIS
35 // int copyfile(char *src, char *dst);
36 //
37 // DESCRIPTION
38 // The copyfile function complements the link and rename functions.
39 //
40 // ARGUMENTS
41 // src - pathname of source file
42 // dst - pathname of destination file
43 //
44 // RETURNS
45 // 0 on success
46 // -1 on error, setting errno appropriately
47 //
48
49 int
copyfile(const char * src,const char * dst)50 copyfile(const char *src, const char *dst)
51 {
52 int src_fd;
53 int dst_fd;
54 char *buffer;
55 long max;
56 long nbytes;
57 long nbytes2;
58 int err;
59 int result;
60
61 trace(("copyfile(\"%s\", \"%s\")\n{\n", src, dst));
62 os_interrupt_cope();
63 result = -1;
64 src_fd = open(src, O_RDONLY, 0666);
65 if (src_fd < 0)
66 goto done;
67 dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0666);
68 if (dst_fd < 0)
69 {
70 err = errno;
71 close(src_fd);
72 errno = err;
73 goto done;
74 }
75
76 max = 1L << 13;
77 errno = 0;
78 buffer = (char *)malloc(max);
79 if (!buffer)
80 {
81 err = errno ? errno : ENOMEM;
82 close(dst_fd);
83 close(src_fd);
84 errno = err;
85 goto done;
86 }
87
88 for (;;)
89 {
90 nbytes = read(src_fd, buffer, max);
91 if (nbytes < 0)
92 {
93 err = errno;
94 close(src_fd);
95 close(dst_fd);
96 free(buffer);
97 errno = err;
98 goto done;
99 }
100 if (nbytes == 0)
101 break;
102
103 nbytes2 = write(dst_fd, buffer, nbytes);
104 if (nbytes2 < 0)
105 {
106 err = errno;
107 close(src_fd);
108 close(dst_fd);
109 free(buffer);
110 errno = err;
111 goto done;
112 }
113 if (nbytes2 != nbytes)
114 {
115 close(src_fd);
116 close(dst_fd);
117 free(buffer);
118 errno = EIO; // weird device, probably
119 goto done;
120 }
121 }
122 free(buffer);
123 if (close(src_fd))
124 {
125 err = errno;
126 close(dst_fd);
127 errno = err;
128 goto done;
129 }
130 result = close(dst_fd);
131
132 //
133 // here for all exits
134 //
135 done:
136 trace(("return %d; /* errno = %d */\n", result, errno));
137 trace(("}\n"));
138 return result;
139 }
140