[comp.os.os2.programmer] Dectection of HPFS File system?

dale@mks.com (Dale Gass) (11/16/90)

I require a portable and efficient method of determining whether a given
drive uses the HPFS file system.

OS/2 1.2 provides such a call, DosQFSAttach, which returns the relevant
information about a drive.

However, this call is not supported under OS/2 1.1 (and I want the
program to remain 1.1 compatible).  Since HPFS was non-existent under
OS/2 1.1, I can easily avoid making this DosQFSAttach call after
checking the version number and finding it to be less than 1.2.
However, since the DOS calls are dynamically linked, the mere external
reference to DosQFAttach in the executable causes the program execution
to fail at load time.

What I require, is a portable way (i.e.  works on OS/2 1.1, 1.2) to
determine whether a drive is a HPFS file system, without using calls
that are unsupported in version 1.1.

One potential solution would be to create a dynamically linked library
(.DLL) to be included if the user is using OS/2 1.1.  This DLL would
contain a stub for DosQFSAttach which would always return values
indicating FAT file systems.  This is not the cleanest solution, as it
requires an extra auxilliary support file.  A less externally visible
solution would be preferred.

Any comments, suggestions, insights, would be greatly appreciated.

-dale

dale@mks.com    uunet!watmath!mks!dale

lsalomo@hubcap.clemson.edu (lsalomo) (11/16/90)

Try using the DosGetProcAddr API to check for the DosQFSAttach API.  If it
returns NULL, then you are running under 1.1 .

This, along in the DosLoadResource (I think that's the API name) also comes
in handy for providing Help Manager support when the program is running under
1.2 , but supports 1.1 .

Cheers,
Q - the "Q"uestor for knowledge (, a degree, etc.)

lsalomo@hubcap.clemson.edu
ibmman@clemson.clemson.edu
=============================================================================
"Gee Wally, I think there's something wrong with the Beaver."
=============================================================================

jfarley@hpspcoi.HP.COM (Jens Farley) (11/17/90)

dale@mks.com (Dale Gass) writes:

> I require a portable and efficient method of determining whether a given
> drive uses the HPFS file system.

I needed to do the same thing a while back.  What I did is have my program
look at the boot sector, which, in 1.2(1), contains a (text) field that
describes the file system.  The field isn't there for 1.1, so if it's not
there, you assume FAT.  (You can determine the offset of this field into
the boot sector by looking at a boot sector in ASCII format, with DEBUG,
SYMDEB, or Norton Utilities, for example.)  Your program can read the boot
sector using the usual DosOpen, DosRead calls if you open the drive for
direct access (by setting the DASD flag).

rommel@lan.informatik.tu-muenchen.dbp.de (Kai-Uwe Rommel) (11/17/90)

In article <1990Nov15.174907.19980@mks.com> dale@mks.com (Dale Gass) writes:
>However, since the DOS calls are dynamically linked, the mere external
>reference to DosQFAttach in the executable causes the program execution
>to fail at load time.
>
>What I require, is a portable way (i.e.  works on OS/2 1.1, 1.2) to
>determine whether a drive is a HPFS file system, without using calls
>that are unsupported in version 1.1.
>

In one of my programs, I have exactly the same problem. Currently, I use
DosGetModuleHandle() and DosGetProcAddress() to obtain the address of
the DosQFSAttach() call, which is DOSCALLS.182 (ordinal). I do this only
if the OS version is 1.2 or higher. I did not yet test the program under
1.1 but I am not very optimistic that it will run. Apparently, the
linker puts in some version number from DOSCALLS.LIB/OS2.LIB which
prevents loading of some programs under 1.1 when they were linked using
the 1.1 tools.

Kai Uwe Rommel

--
/* Kai Uwe Rommel
 * Munich
 * rommel@lan.informatik.tu-muenchen.dbp.de
 */

lsalomo@hubcap.clemson.edu (lsalomo) (11/18/90)

From article <15510005@hpspcoi.HP.COM>, by jfarley@hpspcoi.HP.COM (Jens Farley):
> dale@mks.com (Dale Gass) writes:
> 
>> I require a portable and efficient method of determining whether a given
>> drive uses the HPFS file system.
> 
> I needed to do the same thing a while back.  What I did is have my program
> look at the boot sector, which, in 1.2(1), contains a (text) field that
> describes the file system.  The field isn't there for 1.1, so if it's not
> there, you assume FAT.  (You can determine the offset of this field into
> the boot sector by looking at a boot sector in ASCII format, with DEBUG,
> SYMDEB, or Norton Utilities, for example.)  Your program can read the boot
> sector using the usual DosOpen, DosRead calls if you open the drive for
> direct access (by setting the DASD flag).

No no no no...If IBM (or Microsoft) even get around to porting OS/2 to other
architectures, then your idea will (more likely than not) not work anymore.
However, DosGetProcAddress looks up the API in the .DLL, which will be there
REGARDLESS of what architecture you are on.

Cheers,
Q - the "Q"uestor for knowledge (, a degree, etc.)

lsalomo@hubcap.clemson.edu
ibmman@clemson.clemson.edu
=============================================================================
"Gee Wally, I think there's something wrong with the Beaver."
=============================================================================

jfarley@hpspcoi.HP.COM (Jens Farley) (11/18/90)

lsalomo@hubcap.clemson.edu (lsalomo) writes:

> Try using the DosGetProcAddr API to check for the DosQFSAttach API.  If it
> returns NULL, then you are running under 1.1 .

You have provided a method for determining whether the version of OS/2 
is earlier than 1.2, but this won't help in determining which file
system is in use.

lsalomo@hubcap.clemson.edu (lsalomo) (11/19/90)

From article <15510007@hpspcoi.HP.COM>, by jfarley@hpspcoi.HP.COM (Jens Farley):
> lsalomo@hubcap.clemson.edu (lsalomo) writes:
> 
>> Try using the DosGetProcAddr API to check for the DosQFSAttach API.  If it
>> returns NULL, then you are running under 1.1 .
> 
> You have provided a method for determining whether the version of OS/2 
> is earlier than 1.2, but this won't help in determining which file
> system is in use.

The point of the original article was that the person wanted to check for the
file system type, but if (s)he used the DosQFSAttach API, then the program
would only run on 1.2, when this API was introduced.  However, (s)he needed
it to run on 1.1 also, so I suggested a way to do this.

I never claimed to be able to determine which file system was in use.

Cheers,
Q - the "Q"uestor for knowledge (, a degree, etc.)

lsalomo@hubcap.clemson.edu
ibmman@clemson.clemson.edu
=============================================================================
"Gee Wally, I think there's something wrong with the Beaver."
=============================================================================

lenox@media-lab.MEDIA.MIT.EDU (Lenox H. Brassell) (11/20/90)

In article <11686@hubcap.clemson.edu>, lsalomo@hubcap.clemson.edu (lsalomo) writes:
> 
> No no no no...If IBM (or Microsoft) even get around to porting OS/2 to other
> architectures, then your idea will (more likely than not) not work anymore.
> However, DosGetProcAddress looks up the API in the .DLL, which will be there
> REGARDLESS of what architecture you are on.
> 

Since the entry points described in OS2.DLL are not exported by name,
the DosGetProcAddress() approach leaves something to be desired.  I
understand that the reason you can't use the 1.1 OS/2 toolkit to produce a
1.0 executable is that the ordinal entry points codes have changed between
releases.

If the test you _really_ want to make is for long-filename awareness,
the following (highly version-independent) code will tell you if a
particular device has the restricted FAT naming convention:

   int UsesOnlyFATnames (char chDriveName)
   {
       char szTestDirName[] = "*:/..BadFatDirectoryName";
       USHORT usCode;

       szTestDirName[0] = chDriveName;
       usCode = DosMkDir (szTestDirName, 0L);
       if  (usCode == 0)
	   usCode = DosRmDir (szTestDirName, 0L);

       return usCode != 0;
   }

A disadvantage of this approach is that it requires write access to
the drive in order to work.  An advantage is that it doesn't use
anything that is HPFS-specific: if you are on an OS/2 workstation
which is an NFS client, this test ought to tell you that long
filenames are safe on, say, a remote Unix drive.

lenox@media-lab.MEDIA.MIT.EDU (Lenox H. Brassell) (11/20/90)

This method is better yet: it does not require write access to the
device in order to work.  (It does require read access: I haven't
found any way around that!)  Just be sure that you mark the EXE header
of the program that uses this test to be "longfilename-aware":

    int IsFAT (char chDriveName)
    {
        char szFileSpec[] = "*:123456789";
        HDIR hdir = HDIR_CREATE;
        USHORT usAttribute = FILE_NORMAL;
        USHORT usSearchCount = 1;
        FILEFINDBUF findbuf;
        USHORT cbBuf;
        USHORT usCode;

        szFileSpec[0] = chDriveName;
        usCode = DosFindFirst (szFileSpec, 
            &hdir, usAttribute, &findbuf, (USHORT)sizeof(findbuf),
            &usSearchCount, 0L
            );
        if  (usCode == 0)
            DosFindClose (hdir);

        return usCode == ERROR_FILENAME_EXCED_RANGE;
    }

dans@microsoft.UUCP (Dan SPALDING) (11/21/90)

In article <1990Nov15.174907.19980@mks.com> dale@mks.com (Dale Gass) writes:
>I require a portable and efficient method of determining whether a given
>drive uses the HPFS file system.
>
>
>What I require, is a portable way (i.e.  works on OS/2 1.1, 1.2) to
>determine whether a drive is a HPFS file system, without using calls
>that are unsupported in version 1.1.
>
something you can do is put the call to DosQFSAttach in a segment that is
marked as "LOADONCALL" in the .def file.  then, you only call your IsHpfs()
call when you have already checked the os/2 version number.  In that way, you
avoid the fault on the load of the program because it won't load and fixup the
code segment with the unsupported API call (for v1.1).  When you do call it,
os/2 will load the segment and perform the fixups then instead of at program
startup time with a "PRELOAD" (the default) segment attribute.

Hope this helps.


-- 
------------------------------------------------------------------------
dan spalding -- microsoft systems/languages -- microsoft!dans
"there has not been a word invented that would convey my indifference to
that remark." - paraphrase from hawkeye pierce

rommel@lan.informatik.tu-muenchen.dbp.de (Kai-Uwe Rommel) (11/23/90)

In article <4112@media-lab.MEDIA.MIT.EDU> lenox@media-lab.MEDIA.MIT.EDU (Lenox H. Brassell) writes:
>Since the entry points described in OS2.DLL are not exported by name,
>the DosGetProcAddress() approach leaves something to be desired.  I
>understand that the reason you can't use the 1.1 OS/2 toolkit to produce a
>1.0 executable is that the ordinal entry points codes have changed between
>releases.
I doubt that this is true because it would prevent you from running a
program which was written under 1.0 and 1.1 under 1.2 or newer. Of
course, new ordinals were added. The docs say that ordinals should only
be used if the entry points will remain the same in future versions of
the software and I assume that this is true for the OS itself ...

>If the test you _really_ want to make is for long-filename awareness,
>the following (highly version-independent) code will tell you if a
>particular device has the restricted FAT naming convention:
>
... some code fragment deleted ...
>
>A disadvantage of this approach is that it requires write access to
>the drive in order to work.  An advantage is that it doesn't use

Another method (only requiring read access):
Try to DosOpen(), let's say, "C:\.HPFS.DETECTION" which is invalid for
FAT but valid for HPFS or other future - for example, Unix-compatible,
i.e. BSD - file systems. Simply try a DosOpen() for reading the file,
not for creation. In case of a FAT file system, the return code will be
either ERROR_INVALID_NAME or ERROR_FILENAME_EXCED_RANGE otherwise it
will (probably) indicate the the file was not found or return 0 if it
happens that such a file exists on the disk (in this case, close the
file). 

Since DosOpen() is a call that exists since 1.0 :-) and even is FAPI,
there should not be any portability problems.

Kai Uwe Rommel

--
/* Kai Uwe Rommel
 * Munich
 * rommel@lan.informatik.tu-muenchen.dbp.de
 */

rommel@lan.informatik.tu-muenchen.dbp.de (Kai-Uwe Rommel) (11/23/90)

In article <4114@media-lab.MEDIA.MIT.EDU> lenox@media-lab.MEDIA.MIT.EDU (Lenox H. Brassell) writes:
>            DosFindClose (hdir);
... some code deleted ...
>        return usCode == ERROR_FILENAME_EXCED_RANGE;
>    }

Just for completeness, check also for ERROR_INVALID_NAME. This is not
documented as a possible return code but it happens if the test-name
fits into 8.3 but has ivalid characters in it or, for example, starts
with a dot.

Kai Uwe Rommel

--
/* Kai Uwe Rommel
 * Munich
 * rommel@lan.informatik.tu-muenchen.dbp.de
 */

kenr@microsoft.UUCP (Kenneth Reneris) (11/24/90)

dale@mks.com writes:
| I require a portable and efficient method of determining whether a given
| drive uses the HPFS file system.

dans@microsoft writes:
| something you can do is put the call to DosQFSAttach in a segment that is
| marked as "LOADONCALL" in the .def file.  ...


The default for code and data selectors within an EXE are to
be demand loaded (loadoncall).  They are preloaded when the
application is loaded from remove-able media, or when being run
from accross the network in os/2 versions less then 1.3.   And
since the os will sometimes pre-load the selectors from within
the exe image, you can't really use the "loadoncall" method to
reference the 1.2 (or better) specific function - if for some
reason the selector get's referenced and the function doesn't
exist on the current machine, the program will be crashed by
the os/2 when it fails to get the function address to fixup
the selector.

    a program which uses the "loadoncall" method to reference
    functions not available on the current level of os/2 will
    not work when:
	it's loaded from removable media (floppy drive)
	it's loaded from over the network on os/2 1.0 or 1.1
	or 1.2 when the swap file is on a local hard-disk.
	(1.2 remote booted with a remote swap file would work).
	if a DLL happened to reference the selector

You can use the function DosGetProcAddr to dynamically obtain
the addresses of functions in DLL's, or the OS entry points.
(Note: most of the os/2 functions can only be obtained via
their ordinal numbers.  I believe they are published in an
include file, but for your reference DosQFSAttach is: DOSCALLS.182)

In any event, I wouldn't use QFSAttach for determining the IFS
type.  It doesn't work as you expect accross the network.  It will
return a file-system name of "LAN" if the drive is redirected to
a server.

If you are interested in knowing whether or the file system supports
long files names, you can simply try to create or reference one.
On down-level files systems (or fat) you will get an error when you
try to pass it in a non 8.3 filename.

Another (cheap) method, which was used in a port of LS for
esthetics, looks at the returned FindFirst info. If only the
last-modification date gets returned by the API, the LS program
assumes it was fat and lower cases the filenames before displaying
them; otherwise, it leaves them alone.

    Note: you have to flag the application to be "longnames"
    aware; otherwise, the os will mask out access to non 8.3
    filenames, and will uppercase them before returning them
    to your appliation.  (this is for compatibility with programs
    that do not understand non 8.3 filenames)

                - Ken

fealon@nadia.stgt.sub.org (Frank Fuchs) (11/27/90)

In article <1990Nov15.174907.19980@mks.com> dale@mks.com (Dale Gass) writes:
>
> [...]
>
>However, this call is not supported under OS/2 1.1 (and I want the
>program to remain 1.1 compatible).  Since HPFS was non-existent under
>OS/2 1.1, I can easily avoid making this DosQFSAttach call after
>checking the version number and finding it to be less than 1.2.
>However, since the DOS calls are dynamically linked, the mere external
>reference to DosQFAttach in the executable causes the program execution
>to fail at load time.

The solution to your problem is to use DosQFSAttach as a Run-Time API-Call.
First you check your version number of OS/2 then you make calls to 
DosLoadModule (check your system DLL's for DosQFSAttach) and DosGetProcAddr.
After this you can use DosQFSAttach. Be sure to free the Module with
DosFreeModule. For further information about Runtime-DLL's consult your
manuals (RTFM ;-)

   Bye,

-- 
Fealon, a.k.a. Frank Fuchs (Foxware), fealon@nadia.stgt.sub.org

lenox@media-lab.MEDIA.MIT.EDU (Lenox H. Brassell) (11/28/90)

In article <5670@tuminfo1.lan.informatik.tu-muenchen.dbp.de>, rommel@lan.informatik.tu-muenchen.dbp.de (Kai-Uwe Rommel) writes:

> Try to DosOpen(), let's say, "C:\.HPFS.DETECTION" ... 
> 
> Since DosOpen() is a call that exists since 1.0 :-) and even is FAPI,
> there should not be any portability problems.

There can still be a sharing problem if you get unlucky: someone
might have the file opened already with OPEN_SHARE_DENYREAD or
OPEN_SHARE_DENYREADWRITE options active.

I think DosFindFirst() "wins" over DosOpen() based on this point.