Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2073 dpurdie 1
/*============================================================================
2072 dpurdie 2
** Copyright (C) 1998-2012 Vix Technology, All rights reserved
3
**============================================================================
4
**
5
**  Project/Product : 
6
**  Filename        : CopyFile.c
7
**  Author(s)       : DDP
8
**
9
**  Description     :
10
**                      The program mimics - but a lot faster a Jats Makefile fragment
11
**                      The program will:
12
**
13
**                      Operate in two modes
14
**                          CopyFile
15
**                          DeleteFile
16
**
17
**                      CopyFile (5 args)
18
**                          1) Display the ----- Text dest
19
**                          2) Error if the source is not found
20
**                          3) Create target path if not alraedy existing
21
**                          4) Copy the source to the target - overwritting the target
22
**                          5) Set File mode
23
**                          6) Test for file existence
24
**
2073 dpurdie 25
**                      DeleteFile (3 args)
2072 dpurdie 26
**                          1) Display the ----- Text dest
27
**                          2) Delete the target file
28
**
29
**                      Make paths use '/'
30
**
31
**
32
**  Information     :
33
**   Compiler       : ANSI C++
34
**   Target         : 
35
**
36
***==========================================================================*/
37
 
2073 dpurdie 38
#include <tchar.h>
2072 dpurdie 39
#include <stdio.h>
40
#include <windows.h>
41
 
2073 dpurdie 42
#define MAX_FILE 2000
2072 dpurdie 43
#define INVALID_FILE_ATTIBUTES ((DWORD) -1)
44
 
2073 dpurdie 45
void fullPath ( _TCHAR * src, _TCHAR *dst );
46
VOID ErrorExit (char *lpszMessage, LPTSTR lpszMessage2);
47
void createPaths ( _TCHAR *path );
2072 dpurdie 48
 
2073 dpurdie 49
/*
50
**  Global
51
*/
52
_TCHAR currentDir[MAX_FILE + 1];            /* Current working directory */
53
char  verbose = 1;                          /* Debugging aid */
54
char  copyMode = 0;                         /* Mode */
55
 
2072 dpurdie 56
/*----------------------------------------------------------------------------
57
** FUNCTION           : main
58
**
59
** DESCRIPTION        : Main entry points
60
**
61
**
62
** INPUTS             : Arguments are fixed
2073 dpurdie 63
**                          Mode    - ModeDebug
2072 dpurdie 64
**                          Text    - Text to output
65
**                          dest    - Target Path
2073 dpurdie 66
**                          file    - Source path   [Copy Only]
67
**                          fmode   - File mode     [Copy Only]
2072 dpurdie 68
**
69
** RETURNS            : 0 - All is good
70
**
71
----------------------------------------------------------------------------*/
2073 dpurdie 72
 
73
int _tmain(int argc, _TCHAR* argv[])
2072 dpurdie 74
{
75
 
2073 dpurdie 76
	DWORD rv;
77
	_TCHAR src [MAX_FILE + 1];
78
	_TCHAR dst [MAX_FILE + 1];
79
 
2072 dpurdie 80
    /*
2073 dpurdie 81
    **  Examine the first argument
82
    **  Must be a character string of
83
    **      [0] - Mode : c or d
84
    **      [1] - Verbose : 0 .. 9
2072 dpurdie 85
    */
2073 dpurdie 86
    if ( argc > 1 )
2072 dpurdie 87
    {
2073 dpurdie 88
        if ( argv[1][0] == 'c' ) {
89
            copyMode = 1;
90
        } else if ( argv[1][0] == 'd' ) {
91
            copyMode = 2;
92
        } else {
93
            ErrorExit("CopyFile: Unknown mode",argv[1]);
94
        }
95
 
96
        if ( argv[1][1] >= '0' && argv[1][1] <= '9' ) {
97
            verbose = argv[1][1] - '0';
98
        }
99
    }
100
 
101
    /*
102
    **  If Verbose, then display arguments
103
    */
104
    if ( verbose )
105
    {
2072 dpurdie 106
        int ii;
107
        for ( ii = 0; ii < argc ; ii++ )
108
        {
2073 dpurdie 109
            fprintf(stderr, "Arg%d: %ls:\n", ii, argv[ii] );
2072 dpurdie 110
        }
2073 dpurdie 111
        fprintf(stderr, "Mode   : %d:\n", copyMode );
112
        fprintf(stderr, "Verbose: %d:\n", verbose );
2072 dpurdie 113
        fflush(stderr) ;
114
    }
115
 
116
    /*
2073 dpurdie 117
    **  Determine cwd
118
    **  Used for ab path conversion
119
    */
120
    GetCurrentDirectory( MAX_FILE, currentDir );
121
    if ( verbose )
122
        fprintf(stderr, "CWD: %ls\n", currentDir );
123
 
124
 
125
    /*
2072 dpurdie 126
    **  Determine mode of operation
127
    **      Copy or Delete
128
    */
2073 dpurdie 129
    if ( copyMode == 1 && argc == 6 ) {
130
        fullPath( argv[4], src);
131
        fullPath( argv[3], dst);
132
 
133
    } else if ( copyMode == 2 && argc == 4) {
134
        fullPath( argv[3], dst);
135
 
2072 dpurdie 136
    } else {
2073 dpurdie 137
        fprintf(stderr, "Mode: %d, Args: %d\n", copyMode, argc);
138
        ErrorExit("Incorrect argument count for mode",L"");
2072 dpurdie 139
    }
140
 
141
    /*
142
    **  Display user text
143
    */
2073 dpurdie 144
    fprintf(stderr, "---- %ls %ls\n", argv[2], argv[3]);
2072 dpurdie 145
    fflush(stderr) ;
146
 
147
    /*
148
    **   Check that the source is a file
149
    */
2073 dpurdie 150
    if ( copyMode == 1 )
2072 dpurdie 151
    {
2073 dpurdie 152
        if ( verbose )
153
            fprintf(stderr, "Validate Source File: %ls\n", src);
154
 
155
        rv = GetFileAttributesW( src );
2072 dpurdie 156
        if ( rv == INVALID_FILE_ATTIBUTES )
157
        {
2073 dpurdie 158
    /* Need to be a better message */
159
            fprintf(stderr, "Source: %ls\n", src);
160
            ErrorExit("Error: Source File not found: ", argv[4]);
2072 dpurdie 161
        }
162
    }
163
 
164
    /*
165
    **  Remove the ReadOnly attribute on the dest file
166
    */
2073 dpurdie 167
    if ( verbose )
168
        fprintf(stderr, "Remove target file: %ls\n", dst);
169
    rv = GetFileAttributesW( dst );
2072 dpurdie 170
    if ( rv != INVALID_FILE_ATTIBUTES )
171
    {
172
        if ( verbose )
173
            fprintf(stderr, "FileExists with attr: %ld\n", rv);
174
        if ( rv & FILE_ATTRIBUTE_READONLY )
175
        {
176
            rv &= ~FILE_ATTRIBUTE_READONLY;
2073 dpurdie 177
            rv = SetFileAttributesW( dst, rv );
2072 dpurdie 178
            if ( rv == 0 )
179
            {
2073 dpurdie 180
                ErrorExit("Error: Attempt to allow write access: ", argv[3]);
2072 dpurdie 181
            }
182
        }
183
 
2073 dpurdie 184
        if (! DeleteFile( dst ) )
2072 dpurdie 185
        {
2073 dpurdie 186
                ErrorExit("Error: Deleting file: ", argv[3]);
2072 dpurdie 187
        }
188
    }
2073 dpurdie 189
 
190
    if ( copyMode == 1 )
2072 dpurdie 191
    {
192
        /*
193
        **  Create directories
194
        **  Use the path to the target - not the provided directory
195
        **  as the createPaths function will not create the last element
196
        */
2073 dpurdie 197
        createPaths( dst );
2072 dpurdie 198
 
199
        /*
200
        **   Copy the file
201
        */
2073 dpurdie 202
        if ( ! CopyFile( src, dst, FALSE ) )
2072 dpurdie 203
        {
204
            rv = GetLastError();
205
            fprintf(stderr, "CopyFileLast Error: %ld\n", rv);
2073 dpurdie 206
            ErrorExit("Error: Copy Error: ", argv[4]);
2072 dpurdie 207
        }
208
 
209
        /*
210
        **  Test for files existence
211
        */
2073 dpurdie 212
        if ( verbose )
213
            fprintf(stderr, "Test target was copied: %ls\n", dst);
214
        rv = GetFileAttributesW( dst );
2072 dpurdie 215
        if ( rv == INVALID_FILE_ATTIBUTES )
216
        {
2073 dpurdie 217
    /* Need to be a better message */
218
            ErrorExit("Error: File not found after copy: ", argv[3]);
2072 dpurdie 219
        }
220
 
221
        /*
222
        **  Set the files attributes
223
        **      Assume read-only
224
        */
2073 dpurdie 225
        if ( _tcsstr( argv[5], L"-w" ) )
2072 dpurdie 226
        {
2073 dpurdie 227
            if ( verbose )
228
                fprintf(stderr, "Set target read-only: %ls\n", dst);
229
 
230
            rv |= FILE_ATTRIBUTE_READONLY;
231
            rv &= ~FILE_ATTRIBUTE_NORMAL;
232
            rv = SetFileAttributesW( dst, rv );
233
            if ( rv == 0 )
234
            {
235
                ErrorExit("Error: Setting ReadOnly: ", argv[3]);
236
            }
2072 dpurdie 237
        }
238
    }
239
 
240
    return 0;
241
}
242
 
243
/*----------------------------------------------------------------------------
244
** FUNCTION           : createPaths
245
**
246
** DESCRIPTION        : Create the path to the target
247
**
248
**
249
** INPUTS             : path
2073 dpurdie 250
**                      Assumed to be a \\?\X:\ style
2072 dpurdie 251
**
252
** RETURNS            : Will not return in error
253
**
254
----------------------------------------------------------------------------*/
255
 
2073 dpurdie 256
void createPaths ( _TCHAR *path )
2072 dpurdie 257
{
258
    DWORD rv;
2073 dpurdie 259
    _TCHAR *ptr = path + 7;
2072 dpurdie 260
    while ( *ptr )
261
    {
2073 dpurdie 262
        if ( *ptr == '/' || *ptr == '\\')
2072 dpurdie 263
        {
264
            *ptr = 0;
2073 dpurdie 265
//fprintf(stderr, "createPaths: %ls\n", path);
266
            if ( ! CreateDirectoryW ( path, NULL ))
2072 dpurdie 267
            {
268
                rv = GetLastError();
269
                if ( rv != ERROR_ALREADY_EXISTS )
270
                    ErrorExit("Error: Cound not create directories:", path);
271
            }
272
            *ptr = '\\';
273
        }
274
        ptr++;
275
    }
276
}
277
 
2073 dpurdie 278
 
2072 dpurdie 279
/*----------------------------------------------------------------------------
2073 dpurdie 280
** FUNCTION           : fullPath
281
**
282
** DESCRIPTION        : Creates a full file path for user
283
**                      Convert relative path to ABS path with \\?\ from
284
**                      Convert / into \ for windows
285
**
286
**                      Handle path elements
287
**                          ./                  - Remove
288
**                          /bbb/../            - Remove
289
**                          /aaa/bbb/../../     - Remove
290
**
291
**
292
** INPUTS             : src         - Partial file path
293
**                      dst         - Area to create full name
294
**                                    Assumed to address a MAX_FILE space
295
**
296
** RETURNS            : Nothing
297
**
298
----------------------------------------------------------------------------*/
299
 
300
void fullPath ( _TCHAR * src, _TCHAR *dst )
301
{
302
    _TCHAR *udst = dst;
303
    _TCHAR *usrc = src;
304
	_tcscpy(dst, TEXT("\\\\?\\"));
305
    if ( src[0] && src[1] != ':' )
306
    {
307
	    _tcscat(dst, currentDir );
308
	    _tcscat(dst, TEXT("\\") );
309
    }
310
    udst += _tcslen(udst);
311
    while ( *usrc )
312
    {
313
        if ( *usrc == '/' ) {
314
            *udst++ = '\\';
315
        } else {
316
            *udst++ = *usrc;
317
        }
318
        usrc++;
319
    }
320
    *udst = 0;
321
 
322
    /*
323
    **  Now remove silly relative path bits
324
    */
325
    udst = dst;
326
    while ( *udst )
327
    {
328
        if ( udst[0] == '\\' && udst[1] == '.' && udst[2] == '\\'  )
329
        {
330
            TCHAR* ptr1 = udst;
331
            TCHAR* ptr2 = udst + 2;
332
            while ( *ptr1++ = *ptr2++ ) {}
333
        }
334
        else if ( udst[0] == '\\' && udst[1] == '.' && udst[2] == '.' && udst[3] == '\\'  )
335
        {
336
            TCHAR* ptr = udst - 1;
337
            TCHAR* ptr2 = udst + 3;
338
 
339
            while ( *ptr-- != '\\' )
340
            {
341
                if ( ptr - dst < 6)
342
                {
343
                    *ptr = 0;
344
                    fprintf(stderr, "Path: %ls\n", dst);
345
                    ErrorExit("Bad relative path: ", src);
346
                }
347
            }
348
            ptr++;
349
            udst = ptr;
350
            while ( *ptr++ = *ptr2++ ) {}
351
        }
352
        else
353
        {
354
            *udst++;
355
        }
356
    }
357
 
358
if ( verbose )
359
    fprintf(stderr, "AbsPath: %ls\n", dst);
360
}
361
 
362
 
363
/*----------------------------------------------------------------------------
2072 dpurdie 364
** FUNCTION           : ErrorExit
365
**
366
** DESCRIPTION        : Error processing
367
**                      Report an error and terminate process
368
**
369
**
370
** INPUTS             : lpszMessage     - Message to display
371
**
372
** RETURNS            : Does't return
373
**                      Will exit with bad code
374
**
375
----------------------------------------------------------------------------*/
376
 
2073 dpurdie 377
VOID ErrorExit (char *lpszMessage, LPTSTR lpszMessage2)
2072 dpurdie 378
{ 
2073 dpurdie 379
   fprintf(stderr, "%s%ls\n", lpszMessage,lpszMessage2);
2072 dpurdie 380
   fflush(stderr) ;
381
   ExitProcess(-1);
382
} 
383