NSOpenPanel & NSFileTypeForHFSTypeCode

  • I see in docs for NSOpenPanel and NSSavePanel that it is possible to
    determine filetypes that will be shown/allowed in NSOpenPanel and
    NSSavePanel via setFileTypes method.

    And furthermore, one can use these two functions to take selectivity
    down to the HFS+ OSType file level.

    NSString *NSFileTypeForHFSTypeCode(OSType hfsTypeCode);
    OSType NSHFSTypeCodeFromFileType(NSString *fileType);

    My question is this: Where are the OSType's defined for files/
    filesystems? And is it possible to use setFileTypes to only allow the
    selection of a volume?

    I did find this from November 2002. Is this really still true?

    > No, there is no way to do this at this time.
    >
    >
    > On Oct 31, 2003, at 7:55 AM, Lance Drake wrote:
    >
    >> Hi Cocoa Folks,
    >>
    >> Is it possible to configure the NSOpenPanel dialog to only allow
    >> selection of a 'Volume' and not a directory or file?  I looked at
    > the
    >> NSOpenPanel header and it does not appear so - but then, I've been
    >> under-informed so many times in the past, I thought I should ask.
    >>
    >> Evidently, the Carbon NavServices lib supports a
    > 'NavChooseVolume'
    >> function.  Is this the only one that's available?
  • On Oct 9, 2007, at 12:11 PM, Chris Heimark wrote:

    > I see in docs for NSOpenPanel and NSSavePanel that it is possible to
    > determine filetypes that will be shown/allowed in NSOpenPanel and
    > NSSavePanel via setFileTypes method.
    >
    > And furthermore, one can use these two functions to take selectivity
    > down to the HFS+ OSType file level.
    >
    > NSString *NSFileTypeForHFSTypeCode(OSType hfsTypeCode);
    > OSType NSHFSTypeCodeFromFileType(NSString *fileType);
    >
    > My question is this: Where are the OSType's defined for files/
    > filesystems?

    You probably don't want to go down this route.

    > And is it possible to use setFileTypes to only allow the selection
    > of a volume?

    Yes. You will want to implement:

    - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;

    and return "NO" for non-volumes (you have to determine that by
    whatever logic you want). This disables everything else.

    You also probably want to preseed the directory to root with:
    setDirectory:@"/Volumes", and/or call beginForDirectory:@"/Volumes" --
    unfortunately, /Volumes is slightly different than the 'computer' node.

    Good luck,

    --corbin
  • Corbin Dunn wrote:

    >
    > On Oct 9, 2007, at 12:11 PM, Chris Heimark wrote:
    >
    >> I see in docs for NSOpenPanel and NSSavePanel that it is possible to
    >> determine filetypes that will be shown/allowed in NSOpenPanel and
    >> NSSavePanel via setFileTypes method.
    >>
    >> And furthermore, one can use these two functions to take selectivity
    >> down to the HFS+ OSType file level.
    >>
    >> NSString *NSFileTypeForHFSTypeCode(OSType hfsTypeCode);
    >> OSType NSHFSTypeCodeFromFileType(NSString *fileType);
    >>
    >> My question is this: Where are the OSType's defined for files/
    >> filesystems?
    >
    >
    > You probably don't want to go down this route.
    >
    >> And is it possible to use setFileTypes to only allow the selection
    >> of a volume?
    >
    >
    > Yes. You will want to implement:
    >
    > - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
    >
    > and return "NO" for non-volumes (you have to determine that by
    > whatever logic you want). This disables everything else.
    >
    > You also probably want to preseed the directory to root with:
    > setDirectory:@"/Volumes", and/or call beginForDirectory:@"/Volumes"
    > --  unfortunately, /Volumes is slightly different than the 'computer'
    > node.
    >
    Will this technique show the boot volume (rooted at /)?
  • On Oct 10, 2007, at 4:52 PM, John Stiles wrote:

    >>

    >> You probably don't want to go down this route.
    >>
    >>> And is it possible to use setFileTypes to only allow the
    >>> selection  of a volume?
    >>
    Is the implication of this statement that there are NO fileType
    symbols that would narrow the scope of the selectable files? I
    presume answer is YES.

    >>
    >> Yes. You will want to implement:
    >>
    >> - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
    >>
    >> and return "NO" for non-volumes (you have to determine that by
    >> whatever logic you want). This disables everything else.
    >>
    >> You also probably want to preseed the directory to root with:
    >> setDirectory:@"/Volumes", and/or call beginForDirectory:@"/
    >> Volumes" --  unfortunately, /Volumes is slightly different than
    >> the 'computer' node.
    >>
    > Will this technique show the boot volume (rooted at /)?
    >
    >
    I am going to qualify the list of usable volumes for my application
    using NSTask running diskutil and filtering ONLY for the volumes I
    want - which in my case are USB mounted flash drives.  So I may just
    end up with a NSPopupButton selector filled with only qualified
    volumes. So '/' will not be one of them...

    This appears to be my only alternative ... unless a future OS brings
    a solution ... which I'll know about soon enough ;-)
  • On 10/10/07 5:18 PM, Chris Heimark said:

    >>> You probably don't want to go down this route.
    >>>
    >>>> And is it possible to use setFileTypes to only allow the
    >>>> selection  of a volume?
    >>>
    > Is the implication of this statement that there are NO fileType
    > symbols that would narrow the scope of the selectable files? I
    > presume answer is YES.

    It's too bad that NSOpenPanel (unlike Nav Serv) can't filter by UTI.
    Then you could use kUTTypeVolume aka "public.volume".  You might try
    calling UTTypeCopyDeclaration(kUTTypeVolume) and seeing if there is any
    equivalent HFS type.

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • Am 10.10.2007 um 23:47 schrieb Sean McBride:
    > It's too bad that NSOpenPanel (unlike Nav Serv) can't filter by UTI.
    > Then you could use kUTTypeVolume aka "public.volume".  You might try
    > calling UTTypeCopyDeclaration(kUTTypeVolume) and seeing if there is
    > any
    > equivalent HFS type.

      I think there's 'disk' for disks in Carbon, but I haven't tried
    whether that works with NSOpenPanel.

    Cheers,
    -- M. Uli Kusterer
    http://www.zathras.de
  • On Oct 10, 2007, at 1:52 PM, John Stiles wrote:

    >> Yes. You will want to implement:
    >>
    >> - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
    >>
    >> and return "NO" for non-volumes (you have to determine that by
    >> whatever logic you want). This disables everything else.
    >>
    >> You also probably want to preseed the directory to root with:
    >> setDirectory:@"/Volumes", and/or call beginForDirectory:@"/Volumes"
    >> --  unfortunately, /Volumes is slightly different than the
    >> 'computer' node.
    >>
    > Will this technique show the boot volume (rooted at /)?

    It should -- all volumes should be there. Granted, nothing would stop
    the user from changing directories; they could use "cmd-shift-g" and
    goto another folder. There is a slight bug on Tiger that the "Open"
    button will still be enabled in that case (that bug will be fixed for
    Leopard). To handle that, you can do one final validation on the
    "selected folder" in panel:isValidFilename:.

    -corbin
  • On Oct 10, 2007, at 2:18 PM, Chris Heimark wrote:

    >
    > On Oct 10, 2007, at 4:52 PM, John Stiles wrote:
    >
    >>>
    >
    >>> You probably don't want to go down this route.
    >>>
    >>>> And is it possible to use setFileTypes to only allow the
    >>>> selection  of a volume?
    >>>
    > Is the implication of this statement that there are NO fileType
    > symbols that would narrow the scope of the selectable files? I
    > presume answer is YES.

    It might be possible to make it work, I just don't know off the top of
    my head. Most people implement what you want via the method I described.

    >
    >
    >>>
    >>> Yes. You will want to implement:
    >>>
    >>> - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
    >>>
    >>> and return "NO" for non-volumes (you have to determine that by
    >>> whatever logic you want). This disables everything else.
    >>>
    >>> You also probably want to preseed the directory to root with:
    >>> setDirectory:@"/Volumes", and/or call beginForDirectory:@"/
    >>> Volumes" --  unfortunately, /Volumes is slightly different than
    >>> the 'computer' node.
    >>>
    >> Will this technique show the boot volume (rooted at /)?
    >>
    >>
    > I am going to qualify the list of usable volumes for my application
    > using NSTask running diskutil and filtering ONLY for the volumes I
    > want - which in my case are USB mounted flash drives.  So I may just
    > end up with a NSPopupButton selector filled with only qualified
    > volumes. So '/' will not be one of them...

    So, you won't use the NSOpenPanel at all? It sounds like the
    NSOpenPanel is overkill for what you want, as you want to provide the
    user a very limited selection of items, and your solution may be more
    ideal.

    >
    > This appears to be my only alternative ... unless a future OS brings
    > a solution ... which I'll know about soon enough ;-)
    >

    Validating the items in the NSOpenPanel using the delegate method will
    work. You could enable just the USB flash drive mounted points
    (granted, I don't know how to find out what those are).

    corbin
  • > It's too bad that NSOpenPanel (unlike Nav Serv) can't filter by UTI.
    > Then you could use kUTTypeVolume aka "public.volume".

    This would be the *ideal* way to do it, but it won't work on Tiger.
    Have you logged a bug report requesting this feature? Maybe it will
    appear in a future OS release, but please do log bugs so we know you
    want things like this. Unless the NSOpenPanel developer happens to be
    trolling cocoa-dev, they may miss something like this.

    thanks,
    --corbin
  • I have come close to the desired outcome by setting Panel as follows:
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    [openPanel setTitle:@"Choose Flash Drive Volume"];
    [openPanel setMessage:[NSString stringWithFormat:@"Choose target
    flash drive..."]];
    [openPanel setPrompt:@"Choose"];
    [openPanel setCanCreateDirectories:FALSE];
    [openPanel setCanChooseFiles:FALSE];
    [openPanel setCanChooseDirectories:TRUE];
    [openPanel setExtensionHidden:TRUE];
    [openPanel setRequiredFileType:nil];
    [openPanel setAllowedFileTypes:nil];
    [openPanel setAllowsMultipleSelection:FALSE];
    [openPanel setDelegate:self];

    Coupled with the following delegate setup

    // delegate function for NSOpenPanel
    - (BOOL)panel:(id)sender isValidFilename:(NSString *)filename{
    if ([filename hasPrefix:@"/Volumes/"])
      return TRUE;
    else
      return FALSE;}

    // delegate function for NSOpenPanel
    - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename{
    BOOL isDir = TRUE;
    NSLog (@"OpenPanel: %@:%@", NSHFSTypeOfFile(filename), filename);
    if ([[NSFileManager defaultManager] fileExistsAtPath:filename
    isDirectory:&isDir] && !isDir)
      return TRUE;
    else
      return FALSE;}

    My NSTask / diskutil functionality will be invoked if a /Volume is
    selected and then I'll have a familiar interface to file system for
    user. Though things do look wonky with many greyed out directories
    showing yet unclickable. Note setCanChooseDirectories:TRUE seems to
    be necessary or choose button never goes active. Must be as a result
    of mount points being directories of sorts...

    On Oct 10, 2007, at 7:16 PM, Corbin Dunn wrote:

    >> It's too bad that NSOpenPanel (unlike Nav Serv) can't filter by UTI.
    >> Then you could use kUTTypeVolume aka "public.volume".
    >
    > This would be the *ideal* way to do it, but it won't work on Tiger.
    > Have you logged a bug report requesting this feature? Maybe it will
    > appear in a future OS release, but please do log bugs so we know
    > you want things like this. Unless the NSOpenPanel developer happens
    > to be trolling cocoa-dev, they may miss something like this.
    >
    > thanks,
    > --corbin
    >
  • On Oct 10, 2007, at 2:18 PM, Chris Heimark wrote:

    > I am going to qualify the list of usable volumes for my application
    > using NSTask running diskutil and filtering ONLY for the volumes I
    > want - which in my case are USB mounted flash drives.  So I may just
    > end up with a NSPopupButton selector filled with only qualified
    > volumes. So '/' will not be one of them...

    It's possible to use the IOKit to find mounted flash drives so you
    wouldn't have to use diskutil. I don't know if this is something that
    would be worth doing in your case (since I don't know what your case
    is) since it's not obvious how to do such things. See <http://lists.apple.com/archives/usb/2002/Jan/msg00003.html>.

    What I ended up doing in this case was use getfsstat and iterate over
    the mounted file systems looking for those with f_mntfromname that
    starts with /dev and then use the IOKit to check if it is a mass
    storage device.

    I don't claim this to be the best way to do this, but I found no
    example code. Here's some code (missing a bit of error checking) that
    seems to work.

    [dualg5:~/temp] steve$ cat usb.c
    #include <CoreFoundation/CoreFoundation.h>
    #include <IOKit/IOKitLib.h>
    #include <IOKit/storage/IOMedia.h>
    #include <sys/param.h>
    #include <sys/ucred.h>
    #include <sys/mount.h>
    #include <paths.h>
    #include <libgen.h>

    int main()
    {
    int num = getfsstat( NULL, 0, MNT_NOWAIT );
    struct statfs *fs = malloc( num*sizeof(struct statfs) );

    num = getfsstat( fs, num*sizeof(struct statfs), MNT_NOWAIT );
    int i;
    for( i = 0; i < num; ++i )
    {
      if( strncmp(fs[i].f_mntfromname, _PATH_DEV, strlen(_PATH_DEV)) )
      continue;
      char *disk = basename( fs[i].f_mntfromname );
      CFMutableDictionaryRef dict =
    IOBSDNameMatching( kIOMasterPortDefault, 0, disk );

      if( dict == NULL )
      continue;
      CFDictionarySetValue( dict, CFSTR(kIOMediaLeafKey), kCFBooleanTrue );
      CFDictionarySetValue( dict, CFSTR(kIOMediaEjectableKey),
    kCFBooleanTrue );
      CFDictionarySetValue( dict, CFSTR(kIOMediaWritableKey),
    kCFBooleanTrue );

      io_iterator_t iter;
      // This consumes a reference to the dictionary so don't CFRelease()
    it.
      kern_return_t ret =
    IOServiceGetMatchingServices( kIOMasterPortDefault, dict, &iter );

      if( ret != KERN_SUCCESS || iter == 0 )
      continue;

      io_registry_entry_t entry;
      while( (entry = IOIteratorNext(iter)) )
      {
      io_string_t path;
      ret = IORegistryEntryGetPath( entry, kIOServicePlane, path );
      IOObjectRelease( entry );

      if( ret != KERN_SUCCESS )
        continue;

      char *p = strstr( path, "/IOUSBMassStorageClass" );
      if( p == NULL )
        continue;
      // This is probably not the right way to do this, but it seems to
    work.
      *(p-1) = '\0';
      p = strrchr( path, '/' );
      if( p == NULL )
        continue;
      *p = '\0';

      io_registry_entry_t device =
    IORegistryEntryFromPath( kIOMasterPortDefault, path );

      if( device == MACH_PORT_NULL )
        continue;
      puts( fs[i].f_mntonname );
      // You can get information about the USB device using device
      // with IORegistryEntryCreateCFProperty().
      IOObjectRelease( device );
      // I'm not sure that this iterator will have multiple entries
      // ever but one seems like enough.
      break;
      }
      IOObjectRelease( iter );
    }
    free( fs );
    return 0;
    }
    [dualg5:~/temp] steve$ gcc -Wall usb.c -framework CoreFoundation -
    framework IOKit
    [dualg5:~/temp] steve$ ./a.out
    [dualg5:~/temp] steve$ ./a.out
    /Volumes/NO NAME
    [dualg5:~/temp] steve$ ./a.out
    /Volumes/NO NAME
    /Volumes/Secure II

    The first had no drives plugged in, the second had one drive, and the
    third had two drives.

    Hope this helps.

    --
    Steve Checkoway
  • That is a great approach, not unlike mine of wrapping 'duskutil' in
    an 'sh'ell to do all my parsing for essentially same information,
    witness:

    mainCommand()
    {
    for _volumeMountName in $(ls /Volumes/* | grep ":" | sed s/://)
    do
    diskutil info $_volumeMountName | sed -e s/^\ \ \ // -e s/[\ ]$// |
    while IFS=: read _infoName _infoValue
    do
    _infoValue=`echo $_infoValue | sed s/^[\ ]//`
    if [ "$_infoName" = "" ]
    then
      continue
    fi
    #            echo "'$_infoName'=='$_infoValue'"
    case "$_infoName" in
      "Mount Point")  # sanity
      if [ "$_infoValue" != "$_volumeMountName" ]
      then
        echo "UNQUALIFIED: $_volumeMountName"
        break
      fi
      ;;

      "Read Only")  # cannot use this kind of device
      if [ "$_infoValue" = "Yes" ]
      then
        echo "UNQUALIFIED: $_volumeMountName"
        break
      fi
      ;;

      "Protocol")  # MUST be USB based
      if [ "$_infoValue" != "USB" ]
      then
        echo "UNQUALIFIED: $_volumeMountName"
        break
      fi
      ;;

      "Free Space")  # cache the space available
      _SPACE=$_infoValue
      ;;

      "UUID")    # cache the UUID for future use if qualified
      _UUID=$_infoValue
      ;;

      "Ejectable")  # has to be a plug in volume (last info piece as well)
      if [ "$_infoValue" = "No" ]
      then
        echo "UNQUALIFIED: $_volumeMountName"
        break
      else
        # here is the final candidate
        echo "QUALIFIED: $_volumeMountName, UUID: $_UUID, SPACE: $_SPACE"
        break
      fi
      ;;
    esac
    done
    done
    }

    mainCommand;

    Yielding, on my system, with just 1 USB drive attached:

    UNQUALIFIED: /Volumes/Remember
    UNQUALIFIED: /Volumes/TitaniumData
    UNQUALIFIED: /Volumes/TitaniumTemp
    UNQUALIFIED: /Volumes/TitaniumTiger
    QUALIFIED: /Volumes/chessy, UUID:
    F9DC83F2-0C29-3F9E-8176-67C62877F365, SPACE: 112.8 MB

    So at least two approaches for finding qualified /volumes to present
    to user. Thanks for your help!

    On Oct 10, 2007, at 11:11 PM, Steve Checkoway wrote:

    > On Oct 10, 2007, at 2:18 PM, Chris Heimark wrote:
    >
    >> I am going to qualify the list of usable volumes for my
    >> application using NSTask running diskutil and filtering ONLY for
    >> the volumes I want - which in my case are USB mounted flash
    >> drives.  So I may just end up with a NSPopupButton selector filled
    >> with only qualified volumes. So '/' will not be one of them...
    >
    >
    > What I ended up doing in this case was use getfsstat and iterate
    > over the mounted file systems looking for those with f_mntfromname
    > that starts with /dev and then use the IOKit to check if it is a
    > mass storage device.
    >
  • On Oct 11, 2007, at 3:08 AM, Chris Heimark wrote:

    > That is a great approach, not unlike mine of wrapping 'duskutil' in
    > an 'sh'ell to do all my parsing for essentially same information,
    > witness:
    > [snip]
    > QUALIFIED: /Volumes/chessy, UUID:
    > F9DC83F2-0C29-3F9E-8176-67C62877F365, SPACE: 112.8 MB
    >
    > So at least two approaches for finding qualified /volumes to present
    > to user. Thanks for your help!

    If you want the other information like uuid and size, you can get all
    of that from the io registry. Check out IORegistryExplorer for
    everything that's included. The advantage of doing it in code is you
    don't have to call an external tool. One problem with calling a tool
    is you have to depend on its output not changing.

    --
    Steve Checkoway
  • You're right about 'diskutil' output suddenly being un-parsable with
    any or all software update. It is also an issue having an 'open'
    shell script as a hackable entity in the resources bundle - making my
    intent of limiting volumes accessed to flash drives completely
    vulnerable.

    I'll try your getfsstat() code to see if that might not be the right
    approach for this application - though I do need to get at the UUID
    as well - so maybe I'll have to use the IORegistry as well.

    What is the accepted Cocoa interface to the IORegistry or am I
    limited to lower level calls for that as well?

    On Oct 11, 2007, at 6:34 AM, Steve Checkoway wrote:

    >
    > On Oct 11, 2007, at 3:08 AM, Chris Heimark wrote:
    >
    >> That is a great approach, not unlike mine of wrapping 'duskutil'
    >> in an 'sh'ell to do all my parsing for essentially same
    >> information, witness:
    >> [snip]
    >> QUALIFIED: /Volumes/chessy, UUID:
    >> F9DC83F2-0C29-3F9E-8176-67C62877F365, SPACE: 112.8 MB
    >>
    >> So at least two approaches for finding qualified /volumes to
    >> present to user. Thanks for your help!
    >
    >
    > If you want the other information like uuid and size, you can get
    > all of that from the io registry. Check out IORegistryExplorer for
    > everything that's included. The advantage of doing it in code is
    > you don't have to call an external tool. One problem with calling a
    > tool is you have to depend on its output not changing.
    >
    > --
    > Steve Checkoway
    >
    >
    >
  • At 21:48 -0700 10/10/2007, <cocoa-dev-request...> wrote:
    > From: Chris Heimark <cjheimark...>
    > References: <AAA5A9EB-E3DF-4FC8-AE2C-FFCE72681563...>
    > <05DE3F5B-A65E-4915-A222-7375D5B1E2A7...>
    > <470D3B7B.2000509...>
    > <470F0618-8653-4137-B99F-EDDE1F7C903D...>
    > <20071010214749.210859577...>
    > <C0AC14DA-CFE9-4777-9B3A-A8D4226FEC0D...>
    > In-Reply-To: <C0AC14DA-CFE9-4777-9B3A-A8D4226FEC0D...>
    > Date: Wed, 10 Oct 2007 21:27:21 -0400
    > Message-ID: <46E7B93A-8370-42E8-ABAA-08C40CE4FFF1...>
    > ...
    > // delegate function for NSOpenPanel
    > - (BOOL)panel:(id)sender isValidFilename:(NSString *)filename{
    > if ([filename hasPrefix:@"/Volumes/"])
    > return TRUE;
    > else
    > return FALSE;}

    Note that it's perfectly possible to find mounted volumes outside of /Volumes.

    One possible test is (using Carbon's File Manager) to get an FSRef for that path, then request the nodeID via FSGetCatalogInfo.

    A volume's root directory will always have the nodeID == 2.

    --
    Rainer Brockerhoff  <rainer...>
    Belo Horizonte, Brazil
    "In the affairs of others even fools are wise
    In their own business even sages err."
    Weblog: http://www.brockerhoff.net/bb/viewtopic.php
  • On Oct 11, 2007, at 4:51 AM, Chris Heimark wrote:

    > You're right about 'diskutil' output suddenly being un-parsable with
    > any or all software update. It is also an issue having an 'open'
    > shell script as a hackable entity in the resources bundle - making
    > my intent of limiting volumes accessed to flash drives completely
    > vulnerable.

    Your script didn't work for me. It didn't identify either of my
    drives, probably related to spaces in the name? Also, diskutil isn't
    giving me any uuid info for the two drives.

    > I'll try your getfsstat() code to see if that might not be the right
    > approach for this application - though I do need to get at the UUID
    > as well - so maybe I'll have to use the IORegistry as well.

    For one thing, doing it in code is quite a bit faster.

    [dualg5:~/temp] steve$ time ./a.out
    /Volumes/Secure II
    /Volumes/NO NAME

    real    0m0.099s
    user    0m0.004s
    sys    0m0.059s
    [dualg5:~/temp] steve$ time sh disks.sh
    UNQUALIFIED: /Volumes/MacDjView
    UNQUALIFIED: /Volumes/New
    UNQUALIFIED: /Volumes/w00t

    real    0m9.869s
    user    0m2.001s
    sys    0m1.667s

    (Yes, my hard drive is really called w00t.)

    > What is the accepted Cocoa interface to the IORegistry or am I
    > limited to lower level calls for that as well?

    I don't believe there to be one, but it probably wouldn't be that hard
    to write a wrapper if one _really_ wanted. You just have to read the
    documentation and call the appropriate release functions for the
    various objects when you are finished with them: CFRelease for core
    foundation objects (making sure you follow the create/get rule) and
    IOObjectRelease for the various IOKit objects.

    --
    Steve Checkoway
  • Here is what I got for my flash drive:

        Device Node:        /dev/disk3s2
        Device Identifier:  disk3s2
        Mount Point:        /Volumes/chessy
        Volume Name:        chessy
        File System:        Journaled HFS+
                            Journal size 8192 k at offset 0x3000
        Owners:            Disabled
        Partition Type:    Apple_HFS
        Bootable:          Is bootable
        Media Type:        Generic
        Protocol:          USB
        SMART Status:      Not Supported
        UUID:              F9DC83F2-0C29-3F9E-8176-67C62877F365
        Total Size:        125.8 MB
        Free Space:        112.6 MB
        Read Only:          No
        Ejectable:          Yes

    It may be related to partition type. Since I have made mine
    explicitly Apple_HFS and I did 'diskutil eraseVolume' on it, perhaps
    this is why I have a UUID. And a new UUID is generated every time I
    erase the volume.

    And yes, my script will misbehave with blanks in volume name -
    another reason to not do it that way...

    Thanks for your very helpful responses ;-)

    On Oct 11, 2007, at 9:30 AM, Steve Checkoway wrote:

    > On Oct 11, 2007, at 4:51 AM, Chris Heimark wrote:
    >
    >> You're right about 'diskutil' output suddenly being un-parsable
    >> with any or all software update. It is also an issue having an
    >> 'open' shell script as a hackable entity in the resources bundle -
    >> making my intent of limiting volumes accessed to flash drives
    >> completely vulnerable.
    >
    > Your script didn't work for me. It didn't identify either of my
    > drives, probably related to spaces in the name? Also, diskutil
    > isn't giving me any uuid info for the two drives.
    >
    >
    >> I'll try your getfsstat() code to see if that might not be the
    >> right approach for this application - though I do need to get at
    >> the UUID as well - so maybe I'll have to use the IORegistry as well.
    >
    > For one thing, doing it in code is quite a bit faster.
  • On Oct 11, 2007, at 6:44 AM, Chris Heimark wrote:

    > It may be related to partition type. Since I have made mine
    > explicitly Apple_HFS and I did 'diskutil eraseVolume' on it, perhaps
    > this is why I have a UUID. And a new UUID is generated every time I
    > erase the volume.

    Ah, that must be it. Mine are Fat16, I believe.

    --
    Steve Checkoway
  • I tried the following addition to your code:

    CFTypeRef cftr = IORegistryEntryCreateCFProperty (entry, CFSTR
    (kIOMediaUUIDKey), kCFAllocatorDefault, 0);
    if (cftr)
    {
    CFStringRef uuid = CFCopyDescription (cftr);
    // setup to return our valuable cargo
    if (uuid)
    {
      UUID [ fs[i].f_mntonname ] = CFStringGetCStringPtr (uuid,
    kCFStringEncodingASCII);
      CFRelease (uuid);
    }
    CFRelease (cftr);
    }

    cftr comes back NULL. When I trace the very bizarre path using IO
    Explorer, it turns out "UUID" is not registered. I tried the
    kIOMediaSizeKey as well - and oddly enough, it does not work either -
    returning NULL, though it is definitely in the IO Registry path.
    Puzzled in Paoli.

    On Oct 11, 2007, at 9:55 AM, Steve Checkoway wrote:

    >
    > On Oct 11, 2007, at 6:44 AM, Chris Heimark wrote:
    >
    >> It may be related to partition type. Since I have made mine
    >> explicitly Apple_HFS and I did 'diskutil eraseVolume' on it,
    >> perhaps this is why I have a UUID. And a new UUID is generated
    >> every time I erase the volume.
    >
    >
    > Ah, that must be it. Mine are Fat16, I believe.
    >
    > --
    > Steve Checkoway
    >
    >
    >
  • On Oct 11, 2007, at 9:07 AM, Chris Heimark wrote:

    > I tried the following addition to your code:
    >
    > CFTypeRef cftr = IORegistryEntryCreateCFProperty (entry, CFSTR
    > (kIOMediaUUIDKey), kCFAllocatorDefault, 0);
    > [snip]
    > cftr comes back NULL. When I trace the very bizarre path using IO
    > Explorer, it turns out "UUID" is not registered. I tried the
    > kIOMediaSizeKey as well - and oddly enough, it does not work either
    > - returning NULL, though it is definitely in the IO Registry path.
    > Puzzled in Paoli.

    As you say, UUID doesn't seem to be anywhere in the path. Searching in
    IORegistryExplorer doesn't give me any uuid so I don't know where it's
    getting that value. In fact, searching the registry for the uuid of my
    hard drive as returned by diskutil doesn't show anything so it's not
    showing up there anywhere so you'll have to get that elsewhere.

    As for size, it works for me. You need to call
    IORegistryEntryCreateCFProperty() on entry, as you did, but you need
    to do it before you release it.

    This has probably gone far afield for cocoa-dev. Something like the
    usb list would probably be better.

    --
    Steve Checkoway
previous month october 2007 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