Trying to create an alias file by using the new NSURL methods available with Mac OS X 10.6 !

  • Hello All,

    Using the new NSURL methods available with Cocoa on Mac OS X 10.6, I am
    trying to create an alias file to a certain file. However, this method
    requires a NSURL data type. But I am writing a C program along with an
    objective-C program to accomplish this. The C program would accept the
    inputs as C strings. I would then convert them to NSString and then to NSURL
    strings. However, this is not working :(
    By hardcoding the NSURL strings the program works fine.

    Below are the programs:

    alias.c ===========>
    /*==============================================================*/
    #include<stdio.h>
    #include<AvailabilityMacros.h>

    int CreateAlias(char *, char *);

    int main(int argc, char *argv[])
    {
          #ifdef MAC_OS_X_VERSION_10_6
                  if (CreateAlias(argv[1], argv[2]))
                          printf("Successful\n");
                  else
                          printf("Failed\n");
          #else
                  printf("Cannot create Alias files\n");
          #endif
          return 0;
    }
    /*================================================================*/

    createalias.m (I use the NSURL methods for creating Aliases )
    /*================================================================*/
    #import <Foundation/Foundation.h>

    int CreateAlias(const char *target, const char *aliasname)
    {
          CFStringRef Ref1 = CFStringCreateWithCString(NULL, target,
    kCFStringEncodingASCII);

          CFStringRef Ref2 = CFStringCreateWithCString(NULL, aliasname,
    kCFStringEncodingASCII);

          if (Ref1 == NULL || Ref2 == NULL)
                  exit(1);

          NSString *Destination = (NSString *)Ref1;
          NSString *Alias      = (NSString *)Ref2;
          //NSURL *src =  [NSURL URLWithString:@"file:///Alias_dir/aliastext"];
          //NSURL *dest = [NSURL URLWithString:@
    "file:///Alias_dir/aliastext.alias"];

          NSURL *src =  [NSURL URLWithString:Destination];
          NSURL *dest = [NSURL URLWithString:Alias];

          if (src == nil || dest == nil)
                  exit(1); *// Did not exit here.*

          NSData *bookmarkData                  [
                    src
    bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile
                    includingResourceValuesForKeys:nil
                    relativeToURL:nil
                    error:NULL
                    ];
          if (bookmarkData == NULL)
                  exit(1);  // Did not exit here.

          BOOL ok = [NSURL writeBookmarkData:bookmarkData *// The program is
    failing here*
                          toURL:dest
                          options:0
                          error:NULL];
          if (ok == NO)
                  return 0;

          return 1;
    }
    /*===========================================================================*/

    I also read that CFStringRef can be directly typecasted to NSString *which i
    have done.

    Can anyone tell me what the problem may be ?
    Any comments ?

    Thanks
  • On 1/13/10 10:42 PM, rohan a said:

    > int CreateAlias(const char *target, const char *aliasname)
    > {
    > CFStringRef Ref1 = CFStringCreateWithCString(NULL, target,
    > kCFStringEncodingASCII);

    Don't use kCFStringEncodingASCII, filenames can have non-ASCII characters.

    Save yourself the trouble of all these conversions, and just use the
    NDAlias classes/categories.  See here:
    <http://github.com/nathanday/ndalias>

    It doesn't currently support bookmarks, but a patch would be welcome
    (and pretty easy to add)!

    > Would it be possible to create an alias for a non-existent file ?

    No.  But if its parent folder exists, you could create an alias to the
    parent folder and store the filename.

    Lastly, please don't post the same message to two lists.  Not everyone
    is subscribed to both.

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • Hi,

    Thanks for the response.

    I used kCFStringEncodingASCII, since I am passing a char* strings for the
    filename and alias name through my program.

    Thanks

    On Thu, Jan 14, 2010 at 4:49 AM, Sean McBride <sean...>wrote:

    > On 1/13/10 10:42 PM, rohan a said:
    >
    >> int CreateAlias(const char *target, const char *aliasname)
    >> {
    >> CFStringRef Ref1 = CFStringCreateWithCString(NULL, target,
    >> kCFStringEncodingASCII);
    >
    > Don't use kCFStringEncodingASCII, filenames can have non-ASCII characters.
    >
    > Save yourself the trouble of all these conversions, and just use the
    > NDAlias classes/categories.  See here:
    > <http://github.com/nathanday/ndalias>
    >
    > It doesn't currently support bookmarks, but a patch would be welcome
    > (and pretty easy to add)!
    >
    >> Would it be possible to create an alias for a non-existent file ?
    >
    > No.  But if its parent folder exists, you could create an alias to the
    > parent folder and store the filename.
    >
    > Lastly, please don't post the same message to two lists.  Not everyone
    > is subscribed to both.
    >
    > --
    > ____________________________________________________________
    > Sean McBride, B. Eng                <sean...>
    > Rogue Research                        www.rogue-research.com
    > Mac Software Developer              Montréal, Québec, Canada
    >
    >
    >
  • On Wed, Jan 13, 2010 at 8:16 PM, rohan a <info1686...> wrote:
    > I used kCFStringEncodingASCII, since I am passing a char* strings for the
    > filename and alias name through my program.

    char* does not mean "array of ASCII characters."

    --Kyle Sluder
  • Should I then use kCFStringEncodingUTF8 in this case ?

    On Thu, Jan 14, 2010 at 9:52 AM, Kyle Sluder <kyle.sluder...> wrote:

    > On Wed, Jan 13, 2010 at 8:16 PM, rohan a <info1686...> wrote:
    >> I used kCFStringEncodingASCII, since I am passing a char* strings for the
    >> filename and alias name through my program.
    >
    > char* does not mean "array of ASCII characters."
    >
    > --Kyle Sluder
    >
  • Look at the following functions...

    /*** FileSystem path conversion functions ***/

    /* Extract the contents of the string as a NULL-terminated 8-bit
    string appropriate for passing to POSIX APIs (for example, normalized
    for HFS+).  The string is zero-terminated. false will be returned if
    the conversion results don't fit into the buffer.  Use
    CFStringGetMaximumSizeOfFileSystemRepresentation() if you want to make
    sure the buffer is of sufficient length.
    */
    CF_EXPORT
    Boolean CFStringGetFileSystemRepresentation(CFStringRef string, char
    *buffer, CFIndex maxBufLen) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;

    /* Get the upper bound on the number of bytes required to hold the
    file system representation for the string. This result is returned
    quickly as a very rough approximation, and could be much larger than
    the actual space required. The result includes space for the zero
    termination. If you are allocating a buffer for long-term keeping,
    it's recommended that you reallocate it smaller (to be the right size)
    after calling CFStringGetFileSystemRepresentation().
    */
    CF_EXPORT
    CFIndex CFStringGetMaximumSizeOfFileSystemRepresentation(CFStringRef
    string) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;

    /* Create a CFString from the specified zero-terminated POSIX file
    system representation.  If the conversion fails (possible due to bytes
    in the buffer not being a valid sequence of bytes for the appropriate
    character encoding), NULL is returned.
    */
    CF_EXPORT
    CFStringRef CFStringCreateWithFileSystemRepresentation(CFAllocatorRef
    alloc, const char *buffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
  • On 1/14/10 9:56 AM, rohan a said:

    > Should I then use kCFStringEncodingUTF8 in this case ?

    With NDAlias your function would look like:

    int CreateAlias(const char *target, const char *aliasname)
    {
    NSString* path = [NSFileManager stringWithFileSystemRepresentation:target
      length:strlen(target)];

    NDAlias* alias = [NDAlias aliasWithPath:path];
    }

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • What others have suggested are good, but I also wanted to point out something:

    On Jan 13, 2010, at 9:30 AM, rohan a wrote:

    > Using the new NSURL methods available with Cocoa on Mac OS X 10.6, I am
    > trying to create an alias file to a certain file. However, this method
    > requires a NSURL data type. But I am writing a C program along with an
    > objective-C program to accomplish this. The C program would accept the
    > inputs as C strings. I would then convert them to NSString and then to NSURL
    > strings. However, this is not working :(
    > By hardcoding the NSURL strings the program works fine.

    > #import <Foundation/Foundation.h>
    >
    > int CreateAlias(const char *target, const char *aliasname)
    > {
    > CFStringRef Ref1 = CFStringCreateWithCString(NULL, target,
    > kCFStringEncodingASCII);
    >
    > CFStringRef Ref2 = CFStringCreateWithCString(NULL, aliasname,
    > kCFStringEncodingASCII);
    >
    > if (Ref1 == NULL || Ref2 == NULL)
    > exit(1);
    >
    > NSString *Destination = (NSString *)Ref1;
    > NSString *Alias      = (NSString *)Ref2;
    > //NSURL *src =  [NSURL URLWithString:@"file:///Alias_dir/aliastext"];
    > //NSURL *dest = [NSURL URLWithString:@
    > "file:///Alias_dir/aliastext.alias"];
    >
    > NSURL *src =  [NSURL URLWithString:Destination];
    > NSURL *dest = [NSURL URLWithString:Alias];

    Are the strings file paths or URL strings?  It's important to recognize that those are not the same things.  In your commented-out literals, you are passing file URL strings, which is appropriate.  However, if target and aliasname (and thus Ref1 and Ref2) are not file URL strings but file paths, then you should be creating the NSURL objects with +fileURLWithPath: rather than +URLWithString:.  (And, no, prepending "file://" to a file path does not make it a valid file URL string.  For example, file paths may have spaces in them, while that's not allowed for URL strings.)

    Regards,
    Ken