1 /* vi: set sw=4 ts=4: */
5 * Copyright (C) tons of folks. Tracking down who wrote what
6 * isn't something I'm going to worry about... If you wrote something
7 * here, please feel free to acknowledge your work.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
24 * Permission has been granted to redistribute this code under the GPL.
38 * Copy one file to another, while possibly preserving its modes, times, and
39 * modes. Returns TRUE if successful, or FALSE on a failure with an error
40 * message output. (Failure is not indicated if attributes cannot be set.)
44 copy_file(const char *src_name, const char *dst_name,
45 int set_modes, int follow_links, int force_flag, int quiet_flag)
47 FILE *src_file = NULL;
48 FILE *dst_file = NULL;
49 struct stat srcStatBuf;
50 struct stat dstStatBuf;
55 if (follow_links == TRUE) {
56 src_status = stat(src_name, &srcStatBuf);
57 dst_status = stat(dst_name, &dstStatBuf);
59 src_status = lstat(src_name, &srcStatBuf);
60 dst_status = lstat(dst_name, &dstStatBuf);
65 perror_msg("%s", src_name);
70 if ((dst_status < 0) || force_flag) {
72 dstStatBuf.st_ino = -1;
73 dstStatBuf.st_dev = -1;
76 if ((srcStatBuf.st_dev == dstStatBuf.st_dev) &&
77 (srcStatBuf.st_ino == dstStatBuf.st_ino)) {
79 error_msg("Copying file \"%s\" to itself", src_name);
84 if (S_ISDIR(srcStatBuf.st_mode)) {
85 //fprintf(stderr, "copying directory %s to %s\n", srcName, destName);
86 /* Make sure the directory is writable */
87 dst_status = create_path(dst_name, 0777777 ^ umask(0));
88 if ((dst_status < 0) && (errno != EEXIST)) {
90 perror_msg("%s", dst_name);
94 } else if (S_ISLNK(srcStatBuf.st_mode)) {
95 char link_val[BUFSIZ + 1];
98 //fprintf(stderr, "copying link %s to %s\n", srcName, destName);
99 /* Warning: This could possibly truncate silently, to BUFSIZ chars */
100 link_size = readlink(src_name, &link_val[0], BUFSIZ);
103 perror_msg("%s", src_name);
107 link_val[link_size] = '\0';
108 src_status = symlink(link_val, dst_name);
109 if (src_status < 0) {
111 perror_msg("%s", dst_name);
115 #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
116 if (set_modes == TRUE) {
117 /* Try to set owner, but fail silently like GNU cp */
118 lchown(dst_name, srcStatBuf.st_uid, srcStatBuf.st_gid);
122 } else if (S_ISFIFO(srcStatBuf.st_mode)) {
123 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
124 if (mkfifo(dst_name, 0644) < 0) {
126 perror_msg("%s", dst_name);
130 } else if (S_ISBLK(srcStatBuf.st_mode) || S_ISCHR(srcStatBuf.st_mode)
131 || S_ISSOCK(srcStatBuf.st_mode)) {
132 //fprintf(stderr, "copying soc, blk, or chr %s to %s\n", srcName, destName);
133 if (mknod(dst_name, srcStatBuf.st_mode, srcStatBuf.st_rdev) < 0) {
135 perror_msg("%s", dst_name);
139 } else if (S_ISREG(srcStatBuf.st_mode)) {
140 //fprintf(stderr, "copying regular file %s to %s\n", srcName, destName);
141 src_file = fopen(src_name, "r");
142 if (src_file == NULL) {
144 perror_msg("%s", src_name);
149 dst_file = fopen(dst_name, "w");
150 if (dst_file == NULL) {
152 perror_msg("%s", dst_name);
158 if (copy_file_chunk(src_file, dst_file, srcStatBuf.st_size)==FALSE) {
163 if (fclose(dst_file) < 0) {
168 if (set_modes == TRUE) {
169 /* This is fine, since symlinks never get here */
170 if (chown(dst_name, srcStatBuf.st_uid, srcStatBuf.st_gid) < 0)
171 perror_msg("%s", dst_name);
172 if (chmod(dst_name, srcStatBuf.st_mode) < 0)
173 perror_msg("%s", dst_name);
174 times.actime = srcStatBuf.st_atime;
175 times.modtime = srcStatBuf.st_mtime;
176 if (utime(dst_name, ×) < 0)
177 perror_msg("%s", dst_name);
183 perror_msg("%s", dst_name);
193 c-file-style: "linux"