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