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