1 /*
2    Copyright (c) 2000, 2010, Oracle and/or its affiliates
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 #include "mysys_priv.h"
18 #include "mysys_err.h"
19 #include <my_dir.h> /* for stat */
20 #include <m_string.h>
21 #if defined(HAVE_UTIME_H)
22 #include <utime.h>
23 #elif defined(HAVE_SYS_UTIME_H)
24 #include <sys/utime.h>
25 #elif !defined(HPUX10)
26 #include <time.h>
27 struct utimbuf {
28   time_t actime;
29   time_t modtime;
30 };
31 #endif
32 
33 
34 /*
35   int my_copy(const char *from, const char *to, myf MyFlags)
36 
37   NOTES
38     Ordinary ownership and accesstimes are copied from 'from-file'
39     If MyFlags & MY_HOLD_ORIGINAL_MODES is set and to-file exists then
40     the modes of to-file isn't changed
41     If MyFlags & MY_DONT_OVERWRITE_FILE is set, we will give an error
42     if the file existed.
43 
44   WARNING
45     Don't set MY_FNABP or MY_NABP bits on when calling this function !
46 
47   RETURN
48     0	ok
49     #	Error
50 
51 */
52 
my_copy(const char * from,const char * to,myf MyFlags)53 int my_copy(const char *from, const char *to, myf MyFlags)
54 {
55   size_t Count;
56   my_bool new_file_stat= 0; /* 1 if we could stat "to" */
57   int create_flag;
58   File from_file,to_file;
59   uchar buff[IO_SIZE];
60   MY_STAT stat_buff,new_stat_buff;
61   my_bool file_created= 0;
62   DBUG_ENTER("my_copy");
63   DBUG_PRINT("my",("from %s to %s MyFlags %lu", from, to, MyFlags));
64 
65   from_file=to_file= -1;
66   DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */
67   if (MyFlags & MY_HOLD_ORIGINAL_MODES)		/* Copy stat if possible */
68     new_file_stat= MY_TEST(my_stat((char*) to, &new_stat_buff, MYF(0)));
69 
70   if ((from_file=my_open(from,O_RDONLY | O_SHARE,MyFlags)) >= 0)
71   {
72     if (!my_stat(from, &stat_buff, MyFlags))
73     {
74       my_errno=errno;
75       goto err;
76     }
77     if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat)
78       stat_buff=new_stat_buff;
79     create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC;
80 
81     if ((to_file=  my_create(to,(int) stat_buff.st_mode,
82 			     O_WRONLY | create_flag | O_BINARY | O_SHARE,
83 			     MyFlags)) < 0)
84       goto err;
85 
86     file_created= 1;
87     while ((Count=my_read(from_file, buff, sizeof(buff), MyFlags)) != 0)
88     {
89 	if (Count == (uint) -1 ||
90 	    my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP)))
91 	goto err;
92     }
93 
94     /* sync the destination file */
95     if (MyFlags & MY_SYNC)
96     {
97       if (my_sync(to_file, MyFlags))
98         goto err;
99     }
100 
101     if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags))
102       DBUG_RETURN(-1);				/* Error on close */
103 
104     from_file=to_file= -1;                      /* Files are closed */
105 
106     /* Copy modes if possible */
107 
108     if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
109 	DBUG_RETURN(0);			/* File copyed but not stat */
110     /* Copy modes */
111     if (chmod(to, stat_buff.st_mode & 07777))
112     {
113       my_errno= errno;
114       if (MyFlags & MY_WME)
115         my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL), to, errno);
116       if (MyFlags & MY_FAE)
117         goto err;
118     }
119 #if !defined(__WIN__)
120     /* Copy ownership */
121     if (chown(to, stat_buff.st_uid, stat_buff.st_gid))
122     {
123       my_errno= errno;
124       if (MyFlags & MY_WME)
125         my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_BELL), to, errno);
126       if (MyFlags & MY_FAE)
127         goto err;
128     }
129 #endif
130 
131     if (MyFlags & MY_COPYTIME)
132     {
133       struct utimbuf timep;
134       timep.actime  = stat_buff.st_atime;
135       timep.modtime = stat_buff.st_mtime;
136       (void) utime((char*) to, &timep); /* last accessed and modified times */
137     }
138 
139     DBUG_RETURN(0);
140   }
141 
142 err:
143   if (from_file >= 0) (void) my_close(from_file,MyFlags);
144   if (to_file >= 0)   (void) my_close(to_file, MyFlags);
145 
146   /* attempt to delete the to-file we've partially written */
147   if (file_created)
148     (void) my_delete(to, MyFlags);
149 
150   DBUG_RETURN(-1);
151 } /* my_copy */
152