How can I safely write to a given file path in Cocoa, adding a numeric suffix if necessary?

We want to write to "foo.txt" in this directory. If "foo.txt" already exists, we want to write to "foo-1.txt", etc.

There are several code snippets that try to answer this question, but none of them are satisfactory. For example. this solution in CocoaDev uses the NSFileManager to check for a path to create a safe path. However, this leads to obvious race conditions between getting the path and writing to it. It would be safer to try to write down the atoms and cycle through the numerical suffix on error.

Go to him!

+5
source share
3 answers

Use a system call openwith parameters O_EXCLand O_CREAT. If the file does not exist yet, it openwill create it, open it and return the file handle to you; if it exists, it openwill fail and set errnoto EEXIST.

From there, it should be obvious how to build a loop that tries to increment file names until it returns a file descriptor or generates a file name for too long. In the latter case, make sure you check errnowhen openit failed - EEXISTand ENAMETOOLONG- these are just two errors you might encounter.

+1
source
int fd;
uint32_t counter;
char filename[1024]; // obviously unsafe

sprintf(filename, "foo.txt");
if( (fd = open(filename, O_CREAT | O_EXCL | O_EXLOCK, 0644)) == -1 && errno == EEXIST ) 
{
    for( counter = 1; counter < UINT32_MAX; counter++ ) {
      sprintf(filename, "foo-%u.txt", counter);
      if( (fd = open(filename, O_CREAT | O_EXCL | O_EXLOCK, 0644)) == -1 && errno == EEXIST )
        continue;
      else
        break;
    }
}

if( fd == -1 && counter == UINT32_MAX ) {
    fprintf(stderr, "too many foo-files\n");
} else if( fd == -1 ) {
    fprintf(stderr, "could not open file: %s\n", strerror(errno));
}

// otherwise fd is an open file with an atomically unique name and an
// exclusive lock.
+1
source

:

  • , , .
  • NSFileManager
  • 3 - , / 2

Basically you will create rewritable processing of Cocoa text files, but add a function to provide a unique file name. The big advantage of this approach is that if the power is turned off or your application crashes in the middle of the recording, the semi-prepared file will be deleted in the tmp folder and deleted by the system; left for the user to try to work.

+1
source

All Articles