DosQueryPathInfo() in C++

(DE) Projekte für OS/2, eCS und ArcaOS
(EN) OS/2, eCS and ArcaOS related projects
User avatar
LotharS
Posts: 949
Joined: Sun 29. Dec 2013, 20:07
Location: Düsseldorf

DosQueryPathInfo() in C++

Post by LotharS »

Bitte um große Nachsicht, ich versuche gerade durch C++ zu stolpern. Meine letzten "Schritte" darin sind immerhin 20 Jahre her... An "Hello World" bin ich zwar deutlich vorbei, und eigentlich reizen mich ja auch ernstere Aufgaben. Zum Beispiel diese:

Ich möchte (innerhalb einer Anwendung) u.a. die Größe einer Datei bestimmen. Dazu finde ich in der Toolkit-Hilfe "addendum.inf" ein Beispiel zu DosQueryPathInfo(). Hab's ausprobiert mit dem VisualAge-3.08-Compiler und tut.
Sodann leicht modifiziert, formal zunächst so dass es mit "C++" compiliert wird (auch ok) , und anschließend...
(1) an "FILESTATUS3" ein "L" angehängt und passend dazu "FIL_STANDARDL". Passt ebenfalls.
(2) zwei Zeilen "cout << ..." eingefügt: Der Compiler meldet zur zweiten Zeile "Call does not match any argument list for "ostream::operator<<" im Falle "...L", nicht aber ohne "...L". Suspekt... :?:

Habe schon durchgegoogelt, aber da unterhalten sich anscheinend nur fortgeschrittene Experten. Ich dagegen bräuchte eine Erklärung (oder Fundstelle) als sei ich Fünf... ;)

Zusatzfrage: das Resultat Dateigröße (".cbFile") usw. möchte ich ja eigentlich nicht auf der Konsole anzeigen, sondern weiterreichen an eine verarbeitende Routine. Auch der Pfadname nicht etwa eingetippt, sondern von einer aufrufenden Routine variabel übergeben. Worauf muss ich dabei achten? Oder gibt es etwas viel Einfacheres? Danke im voraus :)

Mein modifizierter Code-Sample hier (vgl.Toolkit- "addendum.inf"):

Code: Select all

 #define INCL_DOSFILEMGR   /* File Manager values */
 #define INCL_DOSERRORS    /* DOS error values    */
 #include <os2.h>
 #include <stdio.h>
 #include <stdlib.h>
#include <iostream.h>      /* -- eingefügt -- */

 int main(VOID) {
 PCSZ  path       = "C:\\config.sys";  /* File to manipulate   */
 FILESTATUS3L  fs = {{0}};           /* Buffer for file information */
 ULONG  ulBufSize = sizeof(FILESTATUS3L);   /* Size of above buffer */
 APIRET rc        = NO_ERROR;        /* Return code                 */

    rc = DosQueryPathInfo(path, /* Path and name of file   */
                FIL_STANDARDL,  /* Request standard (Level 11) info */
                &fs,    /* Buffer for file information     */
                ulBufSize);     /* Size of buffer          */
    if (rc != NO_ERROR) {
        printf("DosQueryPathInfo error: return code = %u\n", rc);
        return 1;
    }

  /* -- eingefügt --  */
  cout << path << endl;       /* ok */
  cout << fs.cbFile << endl;  /* ok ohne "..L", error mit "..L" */

    printf("%s ---  File size: %u bytes\n",path, fs.cbFile);
    printf("Last updated: %d.%d.%d; %d:%2.2d\n",
            fs.fdateLastWrite.day,          /* Day              */
            fs.fdateLastWrite.month,        /* Month            */
            (fs.fdateLastWrite.year+1980L), /* Years since 1980 */
            fs.ftimeLastWrite.hours,        /* Hours            */
            fs.ftimeLastWrite.minutes);     /* Minutes          */

  return NO_ERROR;
}
ehemaliger
Posts: 102
Joined: Wed 22. Nov 2017, 23:46

Post by ehemaliger »

Würde vermuten, daß dieser Steinzeit-Compiler keine 64bit-Datentypen beherrscht und 'LONGLONG' daher als struct bestehen aus je 32bit Low- und Highteil deklariert ist.
User avatar
aschn
Posts: 1363
Joined: Wed 25. Dec 2013, 22:47

Post by aschn »

Das passt. os2def.h:

Code: Select all

    typedef struct _LONGLONG {  /* LONGLONG */
        ULONG ulLo;
        LONG ulHi;
    }LONGLONG;
Andreas Schnellbacher
Andi B.
Posts: 722
Joined: Tue 24. Dec 2013, 16:40

Post by Andi B. »

Das mit LONGLONG hat mich auch schon mal genervt. Irgendwann war auch mal ein "#define INCL_LONGLONG" vorm "#include <os2.h> notwendig/sinnvoll. Ich denke der vac3.08 konnte das nur mit der struct welche aschn schon gepostet hat, ab dem 3.65 geht LONGLONG auch direkt. Rein interessehalber, welches Toolkit verwendest du? Das mit 3.08 mitgelieferte, oder das os2tk45?
User avatar
LotharS
Posts: 949
Joined: Sun 29. Dec 2013, 20:07
Location: Düsseldorf

Post by LotharS »

ehemaliger wrote: Wed 22. Jul 2020, 17:23 Würde vermuten, daß dieser Steinzeit-Compiler keine 64bit-Datentypen beherrscht und 'LONGLONG' daher als struct bestehen aus je 32bit Low- und Highteil deklariert ist.
Der Steinzeit-icc nimmt sogar FILESTATUS4L mit passendem FIL_ Level, und liefert auch Größen > 2GB, printf() spielt sauber mit. Was bisher allein blockiert, ist "cout". Ich wüßte auch nicht was die unter dem "DIR"-Command auch anders tun und (erst) neuere XWP's ebenfalls...
User avatar
LotharS
Posts: 949
Joined: Sun 29. Dec 2013, 20:07
Location: Düsseldorf

Post by LotharS »

Andi B. wrote: Wed 22. Jul 2020, 18:24 Rein interessehalber, welches Toolkit verwendest du? Das mit 3.08 mitgelieferte, oder das os2tk45?
Aktiv ist neuestes os2tk45 aus ANPM. Das ältere aus der eCS-CD2 ist nur formal installiert wegen der WPS-Icons, hängt aber in der config.sys jeweils ganz hinten. Die 'Working Dir' aus all den Icons zu putzen war stupide aber begrenzte Handarbeit, ein Script für die Icons wäre ja mal ganz nett ...

Danke für die Tipps, aber's HomeOffice hat jetzt zu :roll:
ehemaliger
Posts: 102
Joined: Wed 22. Nov 2017, 23:46

Post by ehemaliger »

LotharS wrote: Wed 22. Jul 2020, 19:19Der Steinzeit-icc nimmt sogar FILESTATUS4L mit passendem FIL_ Level, und liefert auch Größen > 2GB, printf() spielt sauber mit.
Du hast sicherlich den Formatspecifier von "%u" in "%llu" geändert und probiert, ob es mit Dateien > 4GB auch noch "funktioniert". Oder? Und die Zusammenfassung der Ausgabe von Pfad, Größe und Datum in einer einzigen printf-Anweisung liefert auch ein korrektes Ergebnis. Wenn das klappt, dann kann der Compiler mehr als ich in Erinnerung hatte...
User avatar
LotharS
Posts: 949
Joined: Sun 29. Dec 2013, 20:07
Location: Düsseldorf

Post by LotharS »

aschn wrote: Wed 22. Jul 2020, 17:45 Das passt. os2def.h:

Code: Select all

    typedef struct _LONGLONG {  /* LONGLONG */
        ULONG ulLo;
        LONG ulHi;
    }LONGLONG;
Danke für den "Bringer" :D :

Code: Select all

  cout << "oben:  " << fs.cbFile.ulHi << endl;
  cout << "unten: " << fs.cbFile.ulLo << endl;
Immerhin funktionierte das "einfache" printf mit "%u" und cbFile > 2GB komplett. Hatte allerdings nur bescheidene < 4GB zur Hand ;)
erdmann
Posts: 574
Joined: Mon 4. Jan 2016, 14:36

Post by erdmann »

Hier ist eigentlich schon soweit alles gesagt: VAC 3.08 beherrscht nur 32-bit integer, VAC 3.65 versteht auch 64-bit integer.
Für den VAC 3.65 compiler muss man die Header mit #define INCL_LONGLONG einbinden damit er NICHT die Hilfsdatenstruktur nimmt, welche aus zwei 32-bit integer ein 64-bit integer "zusammenstückelt" sondern die neuen 64-bit integer Datentypen benutzt (long long, unsigned long long).

Damit man nun für den VAC 3.08 sinnvoll ein unsigned 64-bit integer ausgeben kann ist es also nötig, den Wert als DOUBLE Wert umzurechnen, welches durch folgende Rechnung schnell erledigt ist:
double temp = 4294967296.0 * fs.cbFile.ulHi + 1.0 * fs.cbFile.ulLo;
cout << "Size" << temp << endl;

"cout" ist entsprechend überladen, dass es auch double sowie float Zahlen formatieren kann.

Für signed integer ist allerdings Vorsicht geboten. Da wird die Umwandlung komplizierter.
ehemaliger
Posts: 102
Joined: Wed 22. Nov 2017, 23:46

Post by ehemaliger »

LotharS wrote: Thu 23. Jul 2020, 11:05Immerhin funktionierte das "einfache" printf mit "%u" und cbFile > 2GB komplett. Hatte allerdings nur bescheidene < 4GB zur Hand ;)
Nur scheinbar... Mehr als 4Gb wird nicht gehen und

Code: Select all

printf("%s ---  File size: %u %s\n",path, fs.cbFile, "bytes");
wird entweder abstürzen oder etwas Unerwartetes ausgeben :evil:

Das Verhalten ist übrigens nicht unüblich: Während C++ häufig zu lautstarkem Meckern tendiert, schießt man sich mit C deutlich leichter in den Fuß...