Browse Source

cmFile.h/c : Added cmFileCopy() and cmFileBackup().

master
kevin 10 years ago
parent
commit
92a9b18f44
2 changed files with 175 additions and 24 deletions
  1. 150
    23
      cmFile.c
  2. 25
    1
      cmFile.h

+ 150
- 23
cmFile.c View File

@@ -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
 

+ 25
- 1
cmFile.h View File

@@ -27,7 +27,9 @@ extern "C" {
27 27
     kHandleInvalidFileRC,
28 28
     kStatFailFileRC,
29 29
     kBufAllocFailFileRC,
30
-    kBufTooSmallFileRC
30
+    kBufTooSmallFileRC,
31
+    kFileSysFailFileRC,
32
+
31 33
   };
32 34
 
33 35
   typedef unsigned   cmFileRC_t;
@@ -116,6 +118,28 @@ extern "C" {
116 118
   // Same as cmFileToBuf() but accepts a file name argument.
117 119
   // 'rpt' is the report object to use for error reporting.
118 120
   cmChar_t*  cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned* bufByteCntPtr );
121
+
122
+
123
+  // Copy the file named in srcDir/srcFn/srcExt to a file named dstDir/dstFn/dstExt.
124
+  // Note that srcExt/dstExt may be set to NULL if the file extension is included
125
+  // in srcFn/dstFn.  Likewise srcFn/dstFn may be set to NULL if the file name
126
+  // is included in srcDir/dstDir.
127
+  cmFileRC_t    cmFileCopy( 
128
+    const cmChar_t* srcDir, 
129
+    const cmChar_t* srcFn, 
130
+    const cmChar_t* srcExt, 
131
+    const cmChar_t* dstDir, 
132
+    const cmChar_t* dstFn, 
133
+    const cmChar_t* dstExt,
134
+    cmErr_t*        err);
135
+
136
+
137
+  // This function creates a backup copy of the file 'fn' by duplicating it into
138
+  // a file named fn_#.ext where # is an integer which makes the file name unique.
139
+  // The integers chosen with zero and are incremented until an
140
+  // unused file name is found in the same directory as 'fn'.
141
+  // If the file identified by 'fn' is not found then the function returns quietly.
142
+  cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err );
119 143
   
120 144
   // Allocate and fill a zero terminated string from a file.
121 145
   // Set *bufByteCntPtr to count of bytes read into the buffer.=

Loading…
Cancel
Save