ADC Home > Reference Library > Technical Notes > Legacy Documents > Carbon >

Legacy Documentclose button

Important: This document is part of the Legacy section of the ADC Reference Library. This information should not be used for new development.

Current information on this Reference Library topic can be found here:

CreateResFile and the Poor Man's Search Path

CONTENTS

[Jan 01 1987]






CreateResFile

CreateResFile checks to see if a resource file with a given name exists, and if it does, returns a dupFNErr (-48) error. Unfortunately, to do this check, CreateResFile uses a call that follows the Poor Man's Search Path (PMSP).

CreateResFile checks to see if a resource file with a given name exists, and if it does, returns a dupFNErr (-48) error. Unfortunately, to do the check, CreateResFile calls PBOpenRF, which uses the Poor Man's Search Path (PMSP). For example, if we have a resource file in the System folder named `MyFile' (and no file with that name in the current directory) and we call CreateResFile('MyFile'), ResError will return a dupFNErr, since PBOpenRF will search the current directory first, then search the blessed folder on the same volume. This makes it impossible to use CreateResFile to create the resource file 'MyFile' in the current directory if a file with the same name already exists in a directory that's in the PMSP.

To make sure that CreateResFile will create a resource file in the current directory whether or not a resource file with the same name already exists further down the PMSP, call _Create (PBCreate or Create) before calling CreateResFile:

    err := Create('MyFile',0,myCreator,myType);
        {0 for VRefNum means current volume/directory}
    CreateResFile('MyFile');
    err := ResError; {check for error}

In MPW C:

    err = Create("\pMyFile",0,myCreator,myType);
    CreateResFile("\pMyFile");
    err = ResError();

This works because _Create does not use the PMSP. If we already have `MyFile' in the current directory, _Create will fail with a dupFNErr, then, if `MyFile' has an empty resource fork, CreateResFile will write a resource map, otherwise, CreateResFile will return dupFNErr. If there is no file named 'MyFile' in the current directory, _Create will create one and then CreateResFile will write the resource map.

Notice that we are intentionally ignoring the error from _Create, since we are calling it only to assure that a file named `MyFile' does exist in the current directory.

Please note that SFPutFile does not use the PMSP, but that FSDelete does. SFPutFile returns the vRefNum/WDRefNum of the volume/folder that the user selected. If your program deletes a resource file before creating one with the same name based on information returned from SFPutFile, you can use the following strategy to avoid deleting the wrong file, that is, a file that is not in the directory specified by the vRefNum/WDRefNum returned by SFPutFile, but in some other directory in the PMSP:

    VAR
        wher    : Point;
        reply    : SFReply;
        err        : OSErr;
        oldVol    : Integer;

    ...

        wher.h := 80; wher.v := 90;
        SFPutFile(wher,'','',NIL,reply);
        IF reply.good THEN BEGIN
            err := GetVol(NIL,oldVol); {So we can restore it later}
            err := SetVol(NIL,reply.vRefNum);{for the CreateResFile call}

        {Now for the Create/CreateResFile calls to create a resource file that
        we know is in the current directory}

            err := Create(reply.fName,reply.vRefNum,myCreator,myType);
            CreateResFile(reply.fName); {we'll use the ResError from this ...}

            CASE ResError OF
                noErr:{the create succeeded, go ahead and work with the new
                resource file -- NOTE: at this point, we don't know what's
                in the data fork of the file!!} ;
                dupFNErr: BEGIN {duplicate file name error}
                {the file already existed, so, let's delete it. We're
                now sure that we're deleting the file in the current directory}

                        err:= FSDelete(reply.fName,reply.vRefNum);

                {now that we've deleted the file, let's create the new one,
                again, we know this will be in the current directory}

                err:= Create(reply.fName,reply.vRefNum,myCreator,myType);
                        CreateResFile(reply.fName);
                END; {CASE dupFNErr}
                OTHERWISE        {handle other errors} ;
            END;                {Case ResError}
            err := SetVol(NIL,oldVol);{restore the default directory}
        END; {If reply.good}
    ...

In MPW C:

        Point             wher;
        SFReply        reply;
        OSErr            err;
        short             oldVol;


        wher.h = 80; wher.v = 90;
        SFPutFile(wher,"","",nil,&reply);
        if (reply.good )
        {
            err = GetVol(nil,&oldVol); /*So we can restore it later*/
            err = SetVol(nil,reply.vRefNum);/*for the CreateResFile call*/

            /*Now for the Create/CreateResFile calls to create a resource
            file that we know is in the current directory*/

            err = Create(&reply.fName,reply.vRefNum,myCreator,myType);
            CreateResFile(&reply.fName); /*we'll use the ResError
            from this ...*/

            switch    (ResError())
            {
            case noErr:;/*the create succeeded, go ahead and work with the
            new resource file -- NOTE: at this point, we don't know what's
            in the data fork of the file!!*/
                     break; /* case noErr*/
                case dupFNErr: /*duplicate file name error*/
                        /*the file already existed, so, let's delete it.
                        We're now sure that we're deleting the file in the
                        current directory*/

                err= FSDelete(&reply.fName,reply.vRefNum);

                    /*now that we've deleted the file, let's create the new one,
                    again, we know this will be in the current directory*/

                            err= Create(&reply.fName,reply.vRefNum,
                            myCreator,myType);
                            CreateResFile(&reply.fName);
                    break; /*case dupFNErr*/
                default:;        /*handle other errors*/
            }     /* switch */
            err = SetVol(nil,oldVol);/*restore the default directory*/
        }                    /*if reply.good*/

Note:
OpenResFile uses the PMSP too, so you may have to adopt similar strategies to make sure that you are opening the desired resource file and not some other file further down the PMSP. This is normally not a problem if you use SFGetFile, since SFGetFile does not use the PMSP, in fact, SFGetFile does not open or close files, so it doesn't run into this problem.


References

The File Manager

The Resource Manager

Technical Note M.FL.HFSRuminations

Back to top

Downloadables

Acrobat gif

Acrobat version of this Note (52K)

Download


Back to top


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.