Temporary files

  • Hello, I was just wondering whether there is a simple Cocoa-ish way of
    performing the following: given a path (say pathA) to a file
    (existing or not),
    I would like to get a path (say pathB) with the following properties:

    1. pathB should not point to an existing file.
    2. pathB should point into a temporary / crushable files folder.
    3. (Most important) if a file is written to pathB, it should be
    possible to move
      it to pathA without involving a file copying operation.

    There are two approaches that come to mind:

    1. Take pathB to point into the same directory as pathA. This doesn't
    conform to
      point 2 and so there could be files left littering the disk if the
    application happens
      to crash before it got the chance to delete the file at pathB.
    2. Check on which volume pathA is located and use the Folders API to
    locate
      the temporary files folder on that volume. This should solve the
    problem, but
      somehow doesn't sound like a very clean way of doing it. Also,
    will this behave
      as expected (i.e. conform to point 3 above) if pathA is on a
    networked volume
      or inside a directory structure that was mounted "by hand" in a
    non-standard
      location?

    Cocoa does something like this when saving a file (i.e. it really
    saves it to pathB
    and then deletes the file at pathA and swaps the two files) so my
    question is probably
    whether there's a supported way to tap into this functionality
    without having to
    reimplement it. Regards,

    Martin

    HairerSoft
    http://www.hairersoft.com/
  • As far as I know there is no built-in functionality for this.
    Something like this should work though:

    //Create a temporary path
    NSString *containingDir = [aPath stringByDeletingLastPathComponent];
    char *tempNam = tempnam([containingDir fileSystemRepresentation],
    NULL);

    if (tempNam == NULL)
    {
      return NO;
    }

    NSString *tempFileName = [NSString stringWithCString:tempNam
    encoding:NSASCIIStringEncoding];
    free(tempNam);
    if (tempFileName == nil)
    {
      return NO;
    }

    //Save the file

    //Remove old and rename temp file to new
    [[NSFileManager defaultManager] removeFileAtPath:aPath handler:nil];
    [[NSFileManager defaultManager] movePath:tempFileName toPath:aPath
    handler:nil];

    On Oct 10, 2006, at 8:49 AM, Martin Hairer wrote:

    > Hello, I was just wondering whether there is a simple Cocoa-ish way of
    > performing the following: given a path (say pathA) to a file
    > (existing or not),
    > I would like to get a path (say pathB) with the following properties:
    >
    > 1. pathB should not point to an existing file.
    > 2. pathB should point into a temporary / crushable files folder.
    > 3. (Most important) if a file is written to pathB, it should be
    > possible to move
    > it to pathA without involving a file copying operation.
    >
    > There are two approaches that come to mind:
    >
    > 1. Take pathB to point into the same directory as pathA. This
    > doesn't conform to
    > point 2 and so there could be files left littering the disk if
    > the application happens
    > to crash before it got the chance to delete the file at pathB.
    > 2. Check on which volume pathA is located and use the Folders API
    > to locate
    > the temporary files folder on that volume. This should solve the
    > problem, but
    > somehow doesn't sound like a very clean way of doing it. Also,
    > will this behave
    > as expected (i.e. conform to point 3 above) if pathA is on a
    > networked volume
    > or inside a directory structure that was mounted "by hand" in a
    > non-standard
    > location?
    >
    > Cocoa does something like this when saving a file (i.e. it really
    > saves it to pathB
    > and then deletes the file at pathA and swaps the two files) so my
    > question is probably
    > whether there's a supported way to tap into this functionality
    > without having to
    > reimplement it. Regards,
    >
    > Martin
    >
    > HairerSoft
    > http://www.hairersoft.com/
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<enigma0...>
    >
    > This email sent to <enigma0...>
  • tempnam is not secure, use mkstemp instead.

    On Oct 10, 2006, at 6:14 PM, Ryan Britton wrote:

    > As far as I know there is no built-in functionality for this.
    > Something like this should work though:
    >
    > //Create a temporary path
    > NSString *containingDir = [aPath stringByDeletingLastPathComponent];
    > char *tempNam = tempnam([containingDir fileSystemRepresentation],
    > NULL);
    >
    > if (tempNam == NULL)
    > {
    > return NO;
    > }
    >
    > NSString *tempFileName = [NSString stringWithCString:tempNam
    > encoding:NSASCIIStringEncoding];
    > free(tempNam);
    > if (tempFileName == nil)
    > {
    > return NO;
    > }
    >
    > //Save the file
    >
    > //Remove old and rename temp file to new
    > [[NSFileManager defaultManager] removeFileAtPath:aPath handler:nil];
    > [[NSFileManager defaultManager] movePath:tempFileName toPath:aPath
    > handler:nil];
    >
    >
    > On Oct 10, 2006, at 8:49 AM, Martin Hairer wrote:
    >
    >> Hello, I was just wondering whether there is a simple Cocoa-ish
    >> way of
    >> performing the following: given a path (say pathA) to a file
    >> (existing or not),
    >> I would like to get a path (say pathB) with the following properties:
    >>
    >> 1. pathB should not point to an existing file.
    >> 2. pathB should point into a temporary / crushable files folder.
    >> 3. (Most important) if a file is written to pathB, it should be
    >> possible to move
    >> it to pathA without involving a file copying operation.
    >>
    >> There are two approaches that come to mind:
    >>
    >> 1. Take pathB to point into the same directory as pathA. This
    >> doesn't conform to
    >> point 2 and so there could be files left littering the disk if
    >> the application happens
    >> to crash before it got the chance to delete the file at pathB.
    >> 2. Check on which volume pathA is located and use the Folders API
    >> to locate
    >> the temporary files folder on that volume. This should solve the
    >> problem, but
    >> somehow doesn't sound like a very clean way of doing it. Also,
    >> will this behave
    >> as expected (i.e. conform to point 3 above) if pathA is on a
    >> networked volume
    >> or inside a directory structure that was mounted "by hand" in a
    >> non-standard
    >> location?
    >>
    >> Cocoa does something like this when saving a file (i.e. it really
    >> saves it to pathB
    >> and then deletes the file at pathA and swaps the two files) so my
    >> question is probably
    >> whether there's a supported way to tap into this functionality
    >> without having to
    >> reimplement it. Regards,
    >>
    >> Martin
    >>
    >> HairerSoft
    >> http://www.hairersoft.com/
    >>
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/<enigma0...>
    >>
    >> This email sent to <enigma0...>
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<nirs...>
    >
    > This email sent to <nirs...>

    Best Regards,

    Nir Soffer
  • I believe you could do this with FSFindFolder.

    http://developer.apple.com/documentation/Carbon/Reference/
    Folder_Manager/Reference/reference.html#//apple_ref/c/func/FSFindFolder

    Pass the vRefNum of the volume of pathA and a folder type of
    kChewableItemsFolderType. (To get a vRefNum from a path, call
    FSPathMakeRef and then use FSGetCatalogInfo.)
    Be prepared for this to fail on some volumes, though. For example, on
    a network volume, you won't have a chewable folder. And I believe on
    some volumes you may find that you don't have write permission to
    chewable.

    On Oct 10, 2006, at 8:49 AM, Martin Hairer wrote:

    > Hello, I was just wondering whether there is a simple Cocoa-ish way of
    > performing the following: given a path (say pathA) to a file
    > (existing or not),
    > I would like to get a path (say pathB) with the following properties:
    >
    > 1. pathB should not point to an existing file.
    > 2. pathB should point into a temporary / crushable files folder.
    > 3. (Most important) if a file is written to pathB, it should be
    > possible to move
    > it to pathA without involving a file copying operation.
    >
    > There are two approaches that come to mind:
    >
    > 1. Take pathB to point into the same directory as pathA. This
    > doesn't conform to
    > point 2 and so there could be files left littering the disk if
    > the application happens
    > to crash before it got the chance to delete the file at pathB.
    > 2. Check on which volume pathA is located and use the Folders API
    > to locate
    > the temporary files folder on that volume. This should solve the
    > problem, but
    > somehow doesn't sound like a very clean way of doing it. Also,
    > will this behave
    > as expected (i.e. conform to point 3 above) if pathA is on a
    > networked volume
    > or inside a directory structure that was mounted "by hand" in a
    > non-standard
    > location?
    >
    > Cocoa does something like this when saving a file (i.e. it really
    > saves it to pathB
    > and then deletes the file at pathA and swaps the two files) so my
    > question is probably
    > whether there's a supported way to tap into this functionality
    > without having to
    > reimplement it. Regards,
    >
    > Martin
    >
    > HairerSoft
    > http://www.hairersoft.com/
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/jstiles%
    > 40blizzard.com
    >
    > This email sent to <jstiles...>
  • There are bigger problems with this snippet than a rare race
    condition with tempnam:
    - This code specifies ASCII encoding, but it's possible that paths
    may contain UTF8 characters—and in fact it's likely on non-American
    Macs. Remember, folks, path representations are UTF8, not ASCII!
    - This code deletes the original file before moving the new file
    over. This is risky, and in the worst case it could lead to the old
    file being erased but the new file being left in chewable and
    destroyed. It would be better to do an atomic swap if possible, or
    use the UNIX rename command (which will safely remove a file at the
    destination path).

    On Oct 10, 2006, at 10:54 AM, Nir Soffer wrote:

    > tempnam is not secure, use mkstemp instead.
    >
    > On Oct 10, 2006, at 6:14 PM, Ryan Britton wrote:
    >
    >> As far as I know there is no built-in functionality for this.
    >> Something like this should work though:
    >>
    >> //Create a temporary path
    >> NSString *containingDir = [aPath stringByDeletingLastPathComponent];
    >> char *tempNam = tempnam([containingDir fileSystemRepresentation],
    >> NULL);
    >>
    >> if (tempNam == NULL)
    >> {
    >> return NO;
    >> }
    >>
    >> NSString *tempFileName = [NSString stringWithCString:tempNam
    >> encoding:NSASCIIStringEncoding];
    >> free(tempNam);
    >> if (tempFileName == nil)
    >> {
    >> return NO;
    >> }
    >>
    >> //Save the file
    >>
    >> //Remove old and rename temp file to new
    >> [[NSFileManager defaultManager] removeFileAtPath:aPath handler:nil];
    >> [[NSFileManager defaultManager] movePath:tempFileName
    >> toPath:aPath handler:nil];
    >>
    >>
    >> On Oct 10, 2006, at 8:49 AM, Martin Hairer wrote:
    >>
    >>> Hello, I was just wondering whether there is a simple Cocoa-ish
    >>> way of
    >>> performing the following: given a path (say pathA) to a file
    >>> (existing or not),
    >>> I would like to get a path (say pathB) with the following
    >>> properties:
    >>>
    >>> 1. pathB should not point to an existing file.
    >>> 2. pathB should point into a temporary / crushable files folder.
    >>> 3. (Most important) if a file is written to pathB, it should be
    >>> possible to move
    >>> it to pathA without involving a file copying operation.
    >>>
    >>> There are two approaches that come to mind:
    >>>
    >>> 1. Take pathB to point into the same directory as pathA. This
    >>> doesn't conform to
    >>> point 2 and so there could be files left littering the disk if
    >>> the application happens
    >>> to crash before it got the chance to delete the file at pathB.
    >>> 2. Check on which volume pathA is located and use the Folders API
    >>> to locate
    >>> the temporary files folder on that volume. This should solve
    >>> the problem, but
    >>> somehow doesn't sound like a very clean way of doing it. Also,
    >>> will this behave
    >>> as expected (i.e. conform to point 3 above) if pathA is on a
    >>> networked volume
    >>> or inside a directory structure that was mounted "by hand" in a
    >>> non-standard
    >>> location?
    >>>
    >>> Cocoa does something like this when saving a file (i.e. it really
    >>> saves it to pathB
    >>> and then deletes the file at pathA and swaps the two files) so my
    >>> question is probably
    >>> whether there's a supported way to tap into this functionality
    >>> without having to
    >>> reimplement it. Regards,
    >>>
    >>> Martin
    >>>
    >>> HairerSoft
    >>> http://www.hairersoft.com/
    >>>
    >>>
    >>> _______________________________________________
    >>> Do not post admin requests to the list. They will be ignored.
    >>> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >>> Help/Unsubscribe/Update your Subscription:
    >>> http://lists.apple.com/mailman/options/cocoa-dev/<enigma0...>
    >>>
    >>> This email sent to <enigma0...>
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/<nirs...>
    >>
    >> This email sent to <nirs...>
    >
    >
    > Best Regards,
    >
    > Nir Soffer
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/jstiles%
    > 40blizzard.com
    >
    > This email sent to <jstiles...>
  • On Oct 10, 2006, at 2:03 PM, John Stiles wrote:

    > There are bigger problems with this snippet than a rare race
    > condition with tempnam:
    > - This code specifies ASCII encoding, but it's possible that paths
    > may contain UTF8 characters—and in fact it's likely on non-American
    > Macs. Remember, folks, path representations are UTF8, not ASCII!

    Specifically, Mac OS X currently uses decomposed UTF8 for path
    representations. That is an implementation detail you can (and
    should) insulate yourself from by using the API provided for
    converting between C strings and NS or CF Strings:

    CoreFoundation:

    CFStringGetFileSystemRepresentation
    CFStringCreateWithFileSystemRepresentation

    In Foundation there is an NSString category and NSFileManager methods
    for doing the conversions.

    Jim _______________________________________________
    Do not post admin requests to the list. They will be ignored.
    Cocoa-dev mailing list      (<Cocoa-dev...>)
    Help/Unsubscribe/Update your Subscription:
    http://lists.apple.com/mailman/options/cocoa-dev/<cocoa...>

    This email sent to <cocoa...>
  • > Pass the vRefNum of the volume of pathA and a folder type of
    > kChewableItemsFolderType. (To get a vRefNum from a path, call
    > FSPathMakeRef and then use FSGetCatalogInfo.)
    > Be prepared for this to fail on some volumes, though. For example,
    > on a network volume, you won't have a chewable folder. And I
    > believe on some volumes you may find that you don't have write
    > permission to chewable.

    Thanks for all the feedback. I'll get down that route with the
    fallback of just using the
    folder of pathA if I don't find a chewable or temp files folder on
    the same volume.
    Regards,

    Martin

    HairerSoft
    http://www.hairersoft.com/
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today