|
@@ -2,9 +2,13 @@
|
2
|
2
|
#include "cmGlobal.h"
|
3
|
3
|
#include "cmRpt.h"
|
4
|
4
|
#include "cmErr.h"
|
|
5
|
+#include "cmCtx.h"
|
5
|
6
|
#include "cmFile.h"
|
|
7
|
+#include "cmFileSys.h"
|
6
|
8
|
#include "cmMem.h"
|
7
|
9
|
#include "cmMallocDebug.h"
|
|
10
|
+#include "cmLinkedHeap.h"
|
|
11
|
+#include "cmText.h"
|
8
|
12
|
#include <sys/stat.h>
|
9
|
13
|
cmFileH_t cmFileNullHandle = { NULL };
|
10
|
14
|
|
|
@@ -34,9 +38,9 @@ cmFileRC_t _cmFileError( cmFile_t* p, cmFileRC_t rc, int errNumb, const cmChar_t
|
34
|
38
|
|
35
|
39
|
cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlags_t flags, cmRpt_t* rpt )
|
36
|
40
|
{
|
37
|
|
- char mode[] = "/0/0/0";
|
38
|
|
- cmFile_t* p = NULL;
|
39
|
|
- cmErr_t err;
|
|
41
|
+ char mode[] = "/0/0/0";
|
|
42
|
+ cmFile_t* p = NULL;
|
|
43
|
+ cmErr_t err;
|
40
|
44
|
cmFileRC_t rc;
|
41
|
45
|
|
42
|
46
|
if((rc = cmFileClose(hp)) != kOkFileRC )
|
|
@@ -47,21 +51,21 @@ cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag
|
47
|
51
|
hp->h = NULL;
|
48
|
52
|
|
49
|
53
|
if( cmIsFlag(flags,kReadFileFl) )
|
50
|
|
- mode[0]='r';
|
|
54
|
+ mode[0] = 'r';
|
51
|
55
|
else
|
52
|
56
|
if( cmIsFlag(flags,kWriteFileFl) )
|
53
|
|
- mode[0]='w';
|
|
57
|
+ mode[0] = 'w';
|
54
|
58
|
else
|
55
|
59
|
if( cmIsFlag(flags,kAppendFileFl) )
|
56
|
|
- mode[0]='a';
|
|
60
|
+ mode[0] = 'a';
|
57
|
61
|
else
|
58
|
62
|
cmErrMsg(&err,kInvalidFlagFileRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'.");
|
59
|
63
|
|
60
|
64
|
if( cmIsFlag(flags,kUpdateFileFl) )
|
61
|
|
- mode[1]='+';
|
|
65
|
+ mode[1] = '+';
|
62
|
66
|
|
63
|
67
|
// handle requests to use stdin,stdout,stderr
|
64
|
|
- FILE* sfp = NULL;
|
|
68
|
+ FILE* sfp = NULL;
|
65
|
69
|
if( cmIsFlag(flags,kStdoutFileFl) )
|
66
|
70
|
{
|
67
|
71
|
sfp = stdout;
|
|
@@ -107,7 +111,7 @@ cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag
|
107
|
111
|
}
|
108
|
112
|
}
|
109
|
113
|
|
110
|
|
- hp->h = p;
|
|
114
|
+ hp->h = p;
|
111
|
115
|
|
112
|
116
|
return kOkFileRC;
|
113
|
117
|
}
|
|
@@ -158,7 +162,7 @@ cmFileRC_t cmFileWrite( cmFileH_t h, const void* buf, unsigned bufByteCnt )
|
158
|
162
|
cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByteCnt )
|
159
|
163
|
{
|
160
|
164
|
cmFile_t* p = _cmFileHandleToPtr(h);
|
161
|
|
- unsigned fileflags = 0;
|
|
165
|
+ unsigned fileflags = 0;
|
162
|
166
|
|
163
|
167
|
if( cmIsFlag(flags,kBeginFileFl) )
|
164
|
168
|
fileflags = SEEK_SET;
|
|
@@ -171,7 +175,7 @@ cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt
|
171
|
175
|
else
|
172
|
176
|
return cmErrMsg(&p->err,kInvalidFlagFileRC,"Invalid file seek flag on '%s'.",p->fnStr);
|
173
|
177
|
|
174
|
|
- errno = 0;
|
|
178
|
+ errno = 0;
|
175
|
179
|
if( fseek(p->fp,offsByteCnt,fileflags) != 0 )
|
176
|
180
|
return _cmFileError(p,kSeekFailFileRC,errno,"File seek failed");
|
177
|
181
|
|
|
@@ -181,9 +185,10 @@ cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt
|
181
|
185
|
cmFileRC_t cmFileTell( cmFileH_t h, long* offsPtr )
|
182
|
186
|
{
|
183
|
187
|
assert( offsPtr != NULL );
|
184
|
|
- *offsPtr = -1;
|
185
|
|
- cmFile_t* p = _cmFileHandleToPtr(h);
|
186
|
|
- errno = 0;
|
|
188
|
+ *offsPtr = -1;
|
|
189
|
+ cmFile_t* p = _cmFileHandleToPtr(h);
|
|
190
|
+ errno = 0;
|
|
191
|
+
|
187
|
192
|
if((*offsPtr = ftell(p->fp)) == -1)
|
188
|
193
|
return _cmFileError(p,kTellFailFileRC,errno,"File tell failed");
|
189
|
194
|
return kOkFileRC;
|
|
@@ -222,7 +227,7 @@ cmFileRC_t cmFileByteCountFn( const cmChar_t* fn, cmRpt_t* rpt, unsigned* file
|
222
|
227
|
{
|
223
|
228
|
assert( fileByteCntPtr != NULL );
|
224
|
229
|
cmFileRC_t rc;
|
225
|
|
- cmFileH_t h = cmFileNullHandle;
|
|
230
|
+ cmFileH_t h = cmFileNullHandle;
|
226
|
231
|
if((rc = cmFileOpen(&h,fn,kReadFileFl,rpt)) != kOkFileRC )
|
227
|
232
|
return rc;
|
228
|
233
|
|
|
@@ -241,8 +246,8 @@ cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt
|
241
|
246
|
cmFileH_t h0 = cmFileNullHandle;
|
242
|
247
|
cmFileH_t h1 = cmFileNullHandle;
|
243
|
248
|
|
244
|
|
- char b0[ bufByteCnt ];
|
245
|
|
- char b1[ bufByteCnt ];
|
|
249
|
+ char b0[ bufByteCnt ];
|
|
250
|
+ char b1[ bufByteCnt ];
|
246
|
251
|
|
247
|
252
|
assert(isEqualPtr != NULL );
|
248
|
253
|
*isEqualPtr = true;
|
|
@@ -253,14 +258,14 @@ cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt
|
253
|
258
|
if((rc = cmFileOpen(&h1,fn1,kReadFileFl,rpt)) != kOkFileRC )
|
254
|
259
|
goto errLabel;
|
255
|
260
|
|
256
|
|
- cmFile_t* p0 = _cmFileHandleToPtr(h0);
|
257
|
|
- cmFile_t* p1 = _cmFileHandleToPtr(h1);
|
|
261
|
+ cmFile_t* p0 = _cmFileHandleToPtr(h0);
|
|
262
|
+ cmFile_t* p1 = _cmFileHandleToPtr(h1);
|
258
|
263
|
|
259
|
264
|
while(1)
|
260
|
265
|
{
|
261
|
266
|
size_t n0 = fread(b0,1,bufByteCnt,p0->fp);
|
262
|
267
|
size_t n1 = fread(b1,1,bufByteCnt,p1->fp);
|
263
|
|
- if( n0 != n1 || memcmp(b0,b1,n0)!=0 )
|
|
268
|
+ if( n0 != n1 || memcmp(b0,b1,n0) != 0 )
|
264
|
269
|
{
|
265
|
270
|
*isEqualPtr = false;
|
266
|
271
|
break;
|
|
@@ -285,7 +290,7 @@ const cmChar_t* cmFileName( cmFileH_t h )
|
285
|
290
|
|
286
|
291
|
cmFileRC_t cmFileFnWrite( const cmChar_t* fn, cmRpt_t* rpt, const void* buf, unsigned bufByteCnt )
|
287
|
292
|
{
|
288
|
|
- cmFileH_t h = cmFileNullHandle;
|
|
293
|
+ cmFileH_t h = cmFileNullHandle;
|
289
|
294
|
cmFileRC_t rc;
|
290
|
295
|
|
291
|
296
|
if((rc = cmFileOpen(&h,fn,kWriteFileFl,rpt)) != kOkFileRC )
|
|
@@ -305,7 +310,7 @@ cmChar_t* _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
|
305
|
310
|
|
306
|
311
|
unsigned n = cmFileByteCount(h);
|
307
|
312
|
cmChar_t* buf = NULL;
|
308
|
|
- cmFile_t* p = _cmFileHandleToPtr(h);
|
|
313
|
+ cmFile_t* p = _cmFileHandleToPtr(h);
|
309
|
314
|
|
310
|
315
|
|
311
|
316
|
// if the file size calculation is ok
|
|
@@ -346,7 +351,7 @@ cmChar_t* _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
|
346
|
351
|
|
347
|
352
|
cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigned* bufByteCntPtr )
|
348
|
353
|
{
|
349
|
|
- cmFileH_t h = cmFileNullHandle;
|
|
354
|
+ cmFileH_t h = cmFileNullHandle;
|
350
|
355
|
cmChar_t* buf = NULL;
|
351
|
356
|
|
352
|
357
|
if( cmFileOpen(&h,fn,kReadFileFl | kBinaryFileFl,rpt) != kOkFileRC )
|
|
@@ -360,6 +365,128 @@ cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigne
|
360
|
365
|
return buf;
|
361
|
366
|
}
|
362
|
367
|
|
|
368
|
+cmFileRC_t cmFileCopy(
|
|
369
|
+ const cmChar_t* srcDir,
|
|
370
|
+ const cmChar_t* srcFn,
|
|
371
|
+ const cmChar_t* srcExt,
|
|
372
|
+ const cmChar_t* dstDir,
|
|
373
|
+ const cmChar_t* dstFn,
|
|
374
|
+ const cmChar_t* dstExt,
|
|
375
|
+ cmErr_t* err)
|
|
376
|
+{
|
|
377
|
+ cmFileRC_t rc = kOkFileRC;
|
|
378
|
+ unsigned byteCnt = 0;
|
|
379
|
+ cmChar_t* buf = NULL;
|
|
380
|
+ const cmChar_t* srcPathFn = NULL;
|
|
381
|
+ const cmChar_t* dstPathFn = NULL;
|
|
382
|
+
|
|
383
|
+ // form the source path fn
|
|
384
|
+ if((srcPathFn = cmFsMakeFn(srcDir,srcFn,srcExt,NULL)) == NULL )
|
|
385
|
+ {
|
|
386
|
+ rc = cmErrMsg(err,kFileSysFailFileRC,"The soure file name for dir:%s name:%s ext:%s could not be formed.",cmStringNullGuard(srcDir),cmStringNullGuard(srcFn),cmStringNullGuard(srcExt));
|
|
387
|
+ goto errLabel;
|
|
388
|
+ }
|
|
389
|
+
|
|
390
|
+ // form the dest path fn
|
|
391
|
+ if((dstPathFn = cmFsMakeFn(dstDir,dstFn,dstExt,NULL)) == NULL )
|
|
392
|
+ {
|
|
393
|
+ rc = cmErrMsg(err,kFileSysFailFileRC,"The destination file name for dir:%s name:%s ext:%s could not be formed.",cmStringNullGuard(dstDir),cmStringNullGuard(dstFn),cmStringNullGuard(dstExt));
|
|
394
|
+ goto errLabel;
|
|
395
|
+ }
|
|
396
|
+
|
|
397
|
+ // verify that the source exists
|
|
398
|
+ if( cmFsIsFile(srcPathFn) == false )
|
|
399
|
+ {
|
|
400
|
+ rc = cmErrMsg(err,kOpenFailFileRC,"The source file '%s' does not exist.",cmStringNullGuard(srcPathFn));
|
|
401
|
+ goto errLabel;
|
|
402
|
+ }
|
|
403
|
+
|
|
404
|
+ // read the source file into a buffer
|
|
405
|
+ if((buf = cmFileFnToBuf(srcPathFn,err->rpt,&byteCnt)) == NULL )
|
|
406
|
+ rc = cmErrMsg(err,kReadFailFileRC,"Attempt to fill a buffer from '%s' failed.",cmStringNullGuard(srcPathFn));
|
|
407
|
+ else
|
|
408
|
+ {
|
|
409
|
+ // write the file to the output file
|
|
410
|
+ if( cmFileFnWrite(dstPathFn,err->rpt,buf,byteCnt) != kOkFileRC )
|
|
411
|
+ rc = cmErrMsg(err,kWriteFailFileRC,"An attempt to write a buffer to '%s' failed.",cmStringNullGuard(dstPathFn));
|
|
412
|
+ }
|
|
413
|
+
|
|
414
|
+ errLabel:
|
|
415
|
+ // free the buffer
|
|
416
|
+ cmMemFree(buf);
|
|
417
|
+ cmFsFreeFn(srcPathFn);
|
|
418
|
+ cmFsFreeFn(dstPathFn);
|
|
419
|
+ return rc;
|
|
420
|
+
|
|
421
|
+}
|
|
422
|
+
|
|
423
|
+cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err )
|
|
424
|
+{
|
|
425
|
+ cmFileRC_t rc = kOkFileRC;
|
|
426
|
+ cmChar_t* newName = NULL;
|
|
427
|
+ const cmChar_t* newFn = NULL;
|
|
428
|
+ unsigned n = 0;
|
|
429
|
+ const cmChar_t* srcFn = NULL;
|
|
430
|
+
|
|
431
|
+ // form the name of the backup file
|
|
432
|
+ if((srcFn = cmFsMakeFn(dir,name,ext,NULL)) == NULL )
|
|
433
|
+ {
|
|
434
|
+ rc = cmErrMsg(err,kFileSysFailFileRC,"Backup source file name formation failed.");
|
|
435
|
+ goto errLabel;
|
|
436
|
+ }
|
|
437
|
+
|
|
438
|
+ // if the src file does not exist then there is nothing to do
|
|
439
|
+ if( cmFsIsFile(srcFn) == false )
|
|
440
|
+ return rc;
|
|
441
|
+
|
|
442
|
+ // break the source file name up into dir/fn/ext.
|
|
443
|
+ cmFileSysPathPart_t* pp = NULL;
|
|
444
|
+ if((pp = cmFsPathParts(srcFn)) == NULL || pp->fnStr==NULL)
|
|
445
|
+ {
|
|
446
|
+ rc = cmErrMsg(err,kFileSysFailFileRC,"The file name '%s' could not be parsed into its parts.",cmStringNullGuard(srcFn));
|
|
447
|
+ goto errLabel;
|
|
448
|
+ }
|
|
449
|
+
|
|
450
|
+ // iterate until a unique file name is found
|
|
451
|
+ for(n=0; 1; ++n)
|
|
452
|
+ {
|
|
453
|
+ cmFsFreeFn(newFn);
|
|
454
|
+
|
|
455
|
+ // generate a new file name
|
|
456
|
+ newName = cmTsPrintfP(newName,"%s_%i",pp->fnStr,n);
|
|
457
|
+
|
|
458
|
+ // form the new file name into a complete path
|
|
459
|
+ if((newFn = cmFsMakeFn(pp->dirStr,newName,pp->extStr,NULL)) == NULL )
|
|
460
|
+ {
|
|
461
|
+ rc = cmErrMsg(err,kFileSysFailFileRC,"A backup file name could not be formed for the file '%s'.",cmStringNullGuard(newName));
|
|
462
|
+ goto errLabel;
|
|
463
|
+ }
|
|
464
|
+
|
|
465
|
+ // if the new file name is not already in use ...
|
|
466
|
+ if( cmFsIsFile(newFn) == false )
|
|
467
|
+ {
|
|
468
|
+ // .. then duplicate the file
|
|
469
|
+ if((rc = cmFileCopy(srcFn,NULL,NULL,newFn,NULL,NULL,err)) != kOkFileRC )
|
|
470
|
+ rc = cmErrMsg(err,rc,"The file '%s' could not be duplicated as '%s'.",cmStringNullGuard(srcFn),cmStringNullGuard(newFn));
|
|
471
|
+
|
|
472
|
+ break;
|
|
473
|
+ }
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+ }
|
|
477
|
+
|
|
478
|
+ errLabel:
|
|
479
|
+
|
|
480
|
+ cmFsFreeFn(srcFn);
|
|
481
|
+ cmFsFreeFn(newFn);
|
|
482
|
+ cmMemFree(newName);
|
|
483
|
+ cmFsFreePathParts(pp);
|
|
484
|
+
|
|
485
|
+ return rc;
|
|
486
|
+
|
|
487
|
+}
|
|
488
|
+
|
|
489
|
+
|
363
|
490
|
cmChar_t* cmFileToBuf( cmFileH_t h, unsigned* bufByteCntPtr )
|
364
|
491
|
{ return _cmFileToBuf(h,0,bufByteCntPtr); }
|
365
|
492
|
|