1 #include "copyfile.h"
2 #include "envdeps.h"
3 #include "log.h"
4 
5 #if defined(__OS2__)
6 #define INCL_DOSFILEMGR
7 #define INCL_DOSERRORS
8 #include <os2.h>
9 #elif defined(__NT__)
10 #include <windows.h>
11 #endif
12 
13 #ifdef INCS_NEED_DOT_H
14 #include <errno.h>
15 #include <stdio.h>              // remove
16 #include <fstream.h>
17 #else
18 #include <errno>
19 #include <stdio>              // remove
20 #include <fstream>
21 #endif
22 #include "findfile.h"
23 
24 /* copyfile is expected to ...
25    - return COPY_NOTEXIST if the source path exists, but the specified
26      file cannot be found in this path
27    - return COPY_OTHER if any other error occurs, including
28      non-existance of source or destination path, or others
29    - return COPY_NOERR otherwise.
30 */
31 
32 static int api_copyfile(const char*, const char*);
33 int copyfile_no_api = 0;
34 
copyfile(const char * cpDest,const char * cpSource)35 int copyfile(const char *cpDest, const char *cpSource)
36 {
37 #if defined(__OS2__) || defined(__NT__)
38   if (!copyfile_no_api)
39   {
40       return api_copyfile(cpDest, cpSource);
41   }
42 #endif
43 
44   static unsigned char *cpBuf=new unsigned char[BUFLEN];
45   int retval=COPY_NOERR;
46 
47   logmsg(LOGDBG, "copyfile: using built-in copy routine");
48   logmsg(LOGDBG, "copyfile: copy %s -> %s", cpSource, cpDest);
49 
50   ofstream fo(cpDest,ios::bin|ios::out);
51   if (!fo)
52     {
53       logmsg(LOGDBG, "copyfile: failed to create output stream: %s",
54              strerror(errno));
55       return COPY_OTHER;
56     }
57 
58   ifstream fi(cpSource,ios::bin|ios::in);
59   if (!fi)
60     {
61       logmsg(LOGDBG, "copyfile: failed to open input stream: %s",
62              strerror(errno));
63 
64       fo.close();
65       remove(cpDest);
66 
67       // determine if the path exists or not
68       CArray<CString> *pTemp = findfile(cpSource);
69 
70       if (pTemp!=NULL)
71         {
72           if (pTemp->Size() == 0)
73             {
74               delete pTemp;
75               logmsg(LOGDBG, "copyfile: source file did not exist or had zero length");
76               return COPY_NOTEXIST;
77             }
78           delete pTemp;
79         }
80       return COPY_OTHER;
81     }
82 
83   logmsg(LOGDBG, "copyfile: successfully opened input and output stream.");
84 
85   while (fi)
86     {
87       int gc;
88 
89       fi.read(cpBuf,BUFLEN);
90       if ((gc=fi.gcount())!=0)
91         fo.write(cpBuf,gc);
92       if (!fo)
93         {
94           logmsg(LOGDBG, "copyfile: problem when writing output: %s",
95                  strerror(errno));
96           retval=COPY_OTHER;
97           break;
98         }
99     }
100 
101   fi.close();
102   fo.close();
103   if (retval != COPY_NOERR)                  // failure
104     {
105       logmsg(LOGDBG, "copyfile: some sort of problem, removing destination");
106       remove(cpDest);
107     }
108   return retval;
109 }
110 
111 
112 /* Routine for copying via OS2 or Win32 API. This is a lot faster, so
113    copyfile will call it if possible.
114 */
115 
api_copyfile(const char * cpDest,const char * cpSource)116 static int api_copyfile(const char *cpDest, const char *cpSource)
117 {
118 #if defined(__OS2__)
119   APIRET rc;
120   HDIR FindHandle;
121   FILEFINDBUF3 FindBuffer;
122   ULONG FindCount;
123 
124   logmsg(LOGDBG, "copyfile: using OS/2 API routines");
125 
126   FindHandle = HDIR_CREATE; FindCount = 1;
127   logmsg(LOGDBG, "copyfile: DosFindFirst(%s, ...)", cpSource);
128   rc = DosFindFirst((PSZ)cpSource, &FindHandle,
129                     FILE_ARCHIVED | FILE_SYSTEM | FILE_HIDDEN |
130                     FILE_READONLY,
131                     (PVOID)&FindBuffer,
132                     sizeof(FindBuffer),
133                     &FindCount,
134                     FIL_STANDARD);
135   DosFindClose(FindHandle);
136 
137   logmsg(LOGDBG, "copyfile: DosFindFirst return code is %d", (int)rc);
138 
139   switch(rc)
140     {
141     case ERROR_NO_MORE_FILES:
142         logmsg(LOGDBG, "copyfile: source file does not exist.");
143         return COPY_NOTEXIST;
144     case NO_ERROR: break;
145     default: return COPY_OTHER;
146     }
147 
148   logmsg(LOGDBG, "copyfile: DosCopy(%s,%s,%lx)",
149                           (PSZ)cpSource,(PSZ)cpDest,DCPY_EXISTING);
150 
151   rc = DosCopy((PSZ)cpSource,(PSZ)cpDest,DCPY_EXISTING);
152 
153   logmsg(LOGDBG, "copyfile: DosCopy return code is %d", (int)rc);
154 
155   switch (rc)
156     {
157       case NO_ERROR:             return COPY_NOERR;
158       case ERROR_FILE_NOT_FOUND: return COPY_NOTEXIST;
159       default:                   return COPY_OTHER;
160     }
161 
162 #elif defined(__NT__)
163 
164   DWORD rv;
165 
166   logmsg(LOGDBG, "copyfile: using Win32 API routines");
167   logmsg(LOGDBG, "copyfile: CopyFile(%s, %s, %d)", (char *) cpSource,
168          (char *)cpDest, (int)FALSE);
169 
170   if (CopyFile((LPCTSTR)cpSource,(LPCTSTR)cpDest,FALSE)==TRUE)
171     {
172       logmsg(LOGDBG, "copyfile: CopyFile succeeded");
173       return COPY_NOERR;
174     }
175   else
176     {
177       rv = GetLastError();
178       logmsg(LOGDBG, "copyfile: CopyFile last error is %d", (int) rv);
179       if (rv == ERROR_FILE_NOT_FOUND)
180         {
181           logmsg(LOGDBG, "copyfile: source file does not exist");
182           return COPY_NOTEXIST;
183         }
184       else
185         return COPY_OTHER;
186     }
187 
188 #else
189 
190   /* suppress warnings about unused parameters and functions*/
191   ((void)(cpDest)); ((void)(cpSource));  ((void)(api_copyfile));
192 
193   logmsg(LOGERR, "copyfile: FATAL: don't have a copy API on this platform");
194   return COPY_OTHER;
195 
196 #endif
197 }
198 
199