A rather involved (to me, anyway) "how do I...?" question.

Discussion in 'Apple' started by Don Bruder, Apr 16, 2005.

  1. Don Bruder

    Don Bruder Guest

    Hiya folks...
    Got a "how do I do this?" question for you.

    Given: MacOS 9.x or earlier - Ideally, the solution will be compatible
    back to 7.5.5. (MacOS X solutions need not apply - an app already exists
    for this on X, written to take advantage of X's *nix-based file handling
    methods - I'm interested exclusively in a "Pre-X" implementation.)

    Given: An arbitrarily named datafile (For this discussion, I'll refer to
    it as "Datafile.ext") to be read by my app.

    Given: Both the location and the contents of Datafile.ext can (and
    probably will) be wildly different from one run of the program to the
    next - The only "stability" that can be counted on is that Datafile.ext
    does indeed exist on an accessible storage device of some sort, and that
    it contains all the information needed for the app to run successfully.

    Given: The datafile in turn contains, among other
    irrelevant-to-this-question things, one, and only one, of the following:

    Case A:
    A single "naked" filename - IE "Somefile.ext", with no pathname
    information. In this case, "Somefile.ext" is implied to be (or will be
    created, if it doesn't already exist) in the same directory that houses


    Case B:
    A single directory name, plus a list of one or more filenames - IE
    "DirName" plus at least "Somefile.ext", with the possibility of an
    arbitrary number of arbitrarily named additional files. As in "Case A",
    "DirName" is implied to be (or will be created, if it doesn't already
    exist) in the same directory that houses Datafile.ext. Further, it is
    assumed that the file(s) named in the list either already exist, or will
    be created, within the directory "DirName".

    Given: The file or directory plus files may or may not exist on storage
    device(s) available to the local machine. If they do, they need to be
    read and later used as output destination(s) in later processing. If
    they do not exist, they must be created, and they will be used for
    output in later processing.

    What I've got so far:
    Code that correctly handles the entire process for Case A.

    What I need:
    How to determine whether "DirName" exists, and if it does, then "step
    into" it to look for the additional files named by the datafile.

    I've got partial success - I can easily detect the existence of the
    directory like so:
    Result = FSMakeFSSpec(DatafileFSSpec.vRefnum,

    Looking at Result after the call is going to show me one of two things:
    either noErr (0), or fnfErr (-43). (the assumption is that the file or
    directory of files specified in Datafile.ext will live in the same
    directory with it, which makes the only other possible error, "nsvErr"
    (-35), effectively impossible)

    If I get a -43, a call to FSpDirCreate() using the (valid - just refers
    to a not-yet-existing item) FSSpec I just created hands me back the new
    dirID, which can then be plugged into additional calls to FSMakeFSSpec()
    along with the first and succeeding filenames in the list to determine
    whether they exist or not, and later operate on them as needed. That
    part is trivial.

    The part that's killing me is how to proceed after I get a "noErr"
    result from the first FSMakeFSSpec() call - If that happens, I know that
    the directory specified exists, but I've got no clue what its ID is, or
    how to find out so that I can plug it into the "parID" part of a call to
    FSMakeFSS(vRefnum, parID, <name from the list>, &MyFSSpec);

    Rather ironic that getting a "noErr" result from a toolbox call is a bad
    thing, isn't it? :)

    At this stage, I know that "Path:to_my_DataFile:DirName" exists, and I
    obviously know what "DirName" is, but I have no idea how to turn that
    knowledge into a suitable "parID" value in a new FSMakeFSSpec() call.

    I'd GREATLY prefer to avoid use of anything but built-in capabilities
    (Which rules out the "MoreIsBetter" package) if at all possible, but if
    I've got no other option, I'll go that route.

    Can anyone be of assistance?
    Don Bruder, Apr 16, 2005
    1. Advertisements

  2. Don Bruder

    Miro Jurisic Guest

    FSpGetCatInfo will tell you that. Also, you can create an FSSpec using a
    relative path of the form "dir:file". If dir exists but file doesn't exist
    inside dir, this will return fnfErr and an FSSpec suitable for subsequently
    creating the file.


    Miro Jurisic, Apr 17, 2005
    1. Advertisements

  3. Don Bruder

    Don Bruder Guest

    Searching apple via google is giving me nothing useful (a mention that
    it exists, but no documentation for it) Likewise, searching through
    headers is giving me nada. IM:Files and MPTA, ditto.

    Am I stupid, or just blind? There seems to be no such function in the
    toolbox - Or at least, no mention of it anyplace I can think of to look
    for documentation on it...
    Hmmm... That sounds like it COULD work, if I'm understanding rightly...
    Lemme see if I'm thinking what you're thinking....
    By doing a call something like so:

    Initialize "MyString" to be
    "\pTheDirName:Some unlikely-to-exist filename"

    Result=FSMakFSSpec(KnownvRefNum, DataFileparID, &MyString, &MyFSSpec);
    if (Result = fnfErr) // Should always be true with a properly chosen name
    TheDirID = MyFSSpec.ParID;

    I should end up with TheDirID holding a value suitable for use as the
    parID param in another call to FSMakeFSSpec() to create the FSSpec for
    any files expected to be in the directory?

    One way to konw for sure, I guess... Try it!

    Thanks, guy!
    Don Bruder, Apr 17, 2005
  4. Don Bruder

    Miro Jurisic Guest

    You are right, I mean PBGetCatInfo
    You understand it mostly correctly. There is no point in using an
    unlikely-to-exist filename. Just use the filename you expect to be in that
    directory. If the file exists, you get a valid FSSpec for an existing file. If
    not, you get a valid FSSpec for a non-existent file. Either way, the FSSpec's
    parID is the dirID of that folder.

    Miro Jurisic, Apr 17, 2005
  5. Don Bruder

    Don Bruder Guest

    Aha! That would explain why I had no luck looking for "FSpGet..." Thank
    goodness... I was starting to doubt my own sanity!

    Ugh... parameter blocks... seriously old-school, no question! :) So
    old-school that 99% of the time I forget the "PBxyzzy" routines even
    <nods> I follow that logic, but at the stage of parsing the datafile
    where the DirID is initially needed, I don't yet know (and won't find
    out for a comparatively long time) what filename(s) might or might not
    be involved, so it looks I'm left with either using a "junk" name , or
    resorting to the dredded "PB" calls to harvest the DirID.
    Yep, that's the plan. Later, when I've actually got the list of
    filenames in hand, so to speak, I can sweat over putting together valid
    FSSpecs, but at the point where things are when I initially need the
    DirID, I'm still in the dark as far as filenames, and likely to remain
    there for a fairly long time in computer terms. Since a "junker"
    filename will give me the DirID I need just as well as a "good" one,
    I'll go that route for now - Pass in some ungodly scrambled mess that
    nobody in his right mind is likely to consider as an actual filename,
    pick off the parID that comes back with the fnfErr, and go my merry way.

    Thanks again!
    Don Bruder, Apr 17, 2005
  6. Don Bruder

    Don Bruder Guest

    Erm... Which part of
    "MacOS 9.x or earlier - Ideally, the solution will be compatible
    back to 7.5.5. (MacOS X solutions need not apply"
    was unclear?

    Sorry, Dave, but with all due respect, I asked for how to get a DirID
    when the name of the dir and the path to it is known, not "how to be
    compatible". The plain truth is that I simply don't care about the
    non-english speaking world, thus, don't care about unicode support, and
    I'm not going to bust my hump to deal with idiotically long filenames (a
    "feature" I don't use, and intensely dislike for several reasons that
    aren't worth going into here, but add up to a total of "I hate 'em!")
    unless someone is going to pay me specifically for doing so.

    Since, unfortunately, I don't see anyone tossing wads of cash at me...
    Don Bruder, Apr 17, 2005
  7. Don Bruder

    Greg Guest

    Being compatible with OS 8 and 9 is still no reason for an application
    not to use FSRefs and other parts of a modern API such as Carbon. And
    the answer to your question clearly demonstrates this point. With
    FSRefs finding a dirID given a path is easy: call FSPathMakeRef with
    the path to obtain an FSRef for the corresponding folder, and then pass
    that FSRef to FSGetCatalogInfo to obtain the dirID for the path (though
    a Carbon application probably will have little reasonn even to perform
    this calculation). Trying to find the dirID with pre-Carbon File
    Manager is far more involved: the application has to parse the path
    name itself, making a file system call for each folder along the way
    (and following any Finder aliases encountered) until it reaches last
    folder named by the path.

    Not only can a Carbon app can avail itself of cleaner, more capable and
    a more forwardly-compatible set of APIs, it can more easily be ported
    to OS X. And though OS X may not be the market for this particular app,
    well-written software has a value beyond any specific application. If
    the code uses modern API then it may be well be possible to reuse it in
    an OS X app and reach a much more receptive market. There is no
    significant installed base of Mac customers running systems older than
    8.1 (the earliest Mac OS that supports Carbon) and who also buy new
    software in any great numbers. Whereas those who buy new Macs are also
    the most likely to want to buy new software that showcases the new
    technologies that were the reason they had for buying their new machine
    in the first place.
    Greg, Apr 20, 2005
  8. Don Bruder

    Miro Jurisic Guest

    FSRef APIs require Mac OS 9. Carbon requires Mac OS 8.1. The original posted
    explicitly stated he needs to support systems older than 8.1.
    That's nice, but also completely irrelevant, because he was not looking for a
    dirid from an absolute path, which is what FSPathMakeRef is for.
    Three men are flying in the hot air balloon and suddenly they realize that they
    are lost. Luckily they see a man plowing the earth and ask, "Where are we?". The
    man on the ground thinks for a minute and then answers, "You are in the hot air
    balloon". One of the men in the air then says to his friends, "He was a
    mathematician - he thought before answering, his answer was totally right and
    totally useless"

    Miro Jurisic, Apr 20, 2005
  9. Don Bruder

    Rod Dorman Guest

    Personally I like the
    version better.
    Rod Dorman, Apr 20, 2005
  10. Don Bruder

    kiyookasan Guest

    Here's a snippet from my C++ wrapper of FSSpec, the declaration is
    class LFSSpec : public FSSpec
    Boolean IsFolder(void) const;
    Boolean LFSSpec::FolderExists(void) const;

    IOW, LFSSpec does not declare any data members, only methods.

    Boolean LFSSpec::IsFolder(void) const
    Boolean fIsFolder = false;
    LInfoPBRec pb;
    OSErr error = GetCatInfoNoName(vRefNum, parID, name, &pb.rec);
    if (error==noErr)
    fIsFolder = ( (pb.rec.dirInfo.ioFlAttrib & ioDirMask) != 0 );
    return fIsFolder;

    Boolean LFSSpec::FolderExists(void) const
    return (IsFolder());
    kiyookasan, Apr 21, 2005
  11. Don Bruder

    kiyookasan Guest

    Looks like GetCatInfoNoName is another one of mine; a static member:

    /* static */
    OSErr LFSSpec::GetCatInfoNoName(short vRefNum, long dirID,
    ConstStr255Param name, CInfoPBPtr pb)
    Str31 tempName;
    /* Protection against File Sharing problem */
    if ( (name == NULL) || (name[0] == 0) )
    tempName[0] = 0;
    pb->dirInfo.ioNamePtr = tempName;
    pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */
    pb->dirInfo.ioNamePtr = (StringPtr)name;
    pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
    pb->dirInfo.ioVRefNum = vRefNum;
    pb->dirInfo.ioDrDirID = dirID;
    OSErr error = PBGetCatInfoSync(pb);
    pb->dirInfo.ioNamePtr = NULL;
    return ( error );

    I believe this code came from the appl DTS 'more files' Sample or
    something similar.
    It must have, because I know next to nothing about Classic programming.

    kiyookasan, Apr 21, 2005
  12. Don Bruder

    Greg Guest

    Here's the OS requirements as stated in the original post:
    Note that the phrase "or earlier" is not "and earlier." So presumably
    even an OS 9-only app would meet the requirements, though it would not
    be "ideal". But as I pointed out, supporting systems earlier than 8.1
    is simply not worth the bother.

    About obtaining the dirID from a pathname:
    Since you don't specify what he was looking for, I have no choice but
    to state the question in the poster's own words (I know that quoting
    the actual text is akin to cheating, but...)
    A path to a directory when combined with the name of a directory is an
    absolute path name for that directory. From the question we must assume
    that no other information about the directory is available, therefore
    the only sure way to obtain its dirID would be from its absolute
    The useful post is the one that answers the question; it is the one
    that offers constructive advice, such as writing an OS 8/9 app as a
    Carbon app.

    The useless post is the one that criticizes without taking any stand of
    it own. It is the one that provides no answer to the original question.
    It is the one that in fact does not even know what the original
    question had been.
    Greg, Apr 21, 2005
  13. Don Bruder

    Don Bruder Guest

    To you, perhaps.

    I've accomplished my goal, using Meeroh's advice, and as desired, it
    works all the wy back to the 7.5.5 running on my earliest test machine.
    Which means that all of my requirements have been filled, and continuing
    to dissect the rightness or wrongness of doing it this way is a
    pointless waste of time.

    So, can we cease with the necrohipposadism* now?

    (According to the radio, it's "Use a big word day", so I think I've
    officially done my part...)

    * beating a dead horse
    Don Bruder, Apr 21, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.