platform/os2.c
changeset 407 81646aa3f6f8
parent 404 d08723d994c1
child 411 4907a4f94872
equal deleted inserted replaced
406:bd580c7b1bf0 407:81646aa3f6f8
    15 #define INCL_DOSSEMAPHORES
    15 #define INCL_DOSSEMAPHORES
    16 #define INCL_DOSDATETIME
    16 #define INCL_DOSDATETIME
    17 #define INCL_DOSFILEMGR
    17 #define INCL_DOSFILEMGR
    18 #define INCL_DOSMODULEMGR
    18 #define INCL_DOSMODULEMGR
    19 #define INCL_DOSERRORS
    19 #define INCL_DOSERRORS
       
    20 #define INCL_DOSPROCESS
    20 #define INCL_DOSDEVICES
    21 #define INCL_DOSDEVICES
       
    22 #define INCL_DOSDEVIOCTL
       
    23 #define INCL_DOSMISC
    21 #include <os2.h>
    24 #include <os2.h>
    22 
    25 
    23 #include <stdlib.h>
    26 #include <stdlib.h>
    24 #include <errno.h>
    27 #include <errno.h>
    25 #include <string.h>
    28 #include <string.h>
    26 #include <assert.h>
    29 #include <assert.h>
       
    30 #include <time.h>
       
    31 #include <ctype.h>
       
    32 
       
    33 #define __PHYSICSFS_INTERNAL__
       
    34 #include "physfs_internal.h"
       
    35 
       
    36 const char *__PHYSFS_platformDirSeparator = "\\";
    27 
    37 
    28 
    38 
    29 static APIRET os2err(APIRET retval)
    39 static APIRET os2err(APIRET retval)
    30 {
    40 {
    31     const char *err = NULL;
    41     const char *err = NULL;
    60 
    70 
    61         case ERROR_NOT_DOS_DISK:
    71         case ERROR_NOT_DOS_DISK:
    62             err = "Not a DOS disk";
    72             err = "Not a DOS disk";
    63             break;
    73             break;
    64 
    74 
    65         case ERROR_DRIVE_LOCKED:
       
    66             err = "Drive is locked";
       
    67             break;
       
    68 
       
    69         case ERROR_SHARING_VIOLATION:
    75         case ERROR_SHARING_VIOLATION:
    70             err = "Sharing violation";
    76             err = "Sharing violation";
    71             break;
    77             break;
    72 
    78 
    73         case ERROR_CANNOT_MAKE:
    79         case ERROR_CANNOT_MAKE:
    76 
    82 
    77         case ERROR_DEVICE_IN_USE:
    83         case ERROR_DEVICE_IN_USE:
    78             err = "Device already in use";
    84             err = "Device already in use";
    79             break;
    85             break;
    80 
    86 
    81         case ERROR_DRIVE_LOCKED:
       
    82             err = "Drive is locked";
       
    83             break;
       
    84 
       
    85         case ERROR_OPEN_FAILED:
    87         case ERROR_OPEN_FAILED:
    86             err = "Open failed";
    88             err = "Open failed";
    87             break;
    89             break;
    88 
    90 
    89         case ERROR_DISK_FULL:
    91         case ERROR_DISK_FULL:
    90             err = "Disk is full";
    92             err = "Disk is full";
    91             break;
    93             break;
    92 
    94 
    93         case ERROR_DISK_FULL:
    95         case ERROR_PIPE_BUSY:
    94             err = "Pipe busy";
    96             err = "Pipe busy";
    95             break;
    97             break;
    96 
    98 
    97         case ERROR_SHARING_BUFFER_EXCEEDED:
    99         case ERROR_SHARING_BUFFER_EXCEEDED:
    98             err = "Sharing buffer exceeded";
   100             err = "Sharing buffer exceeded";
   102         case ERROR_META_EXPANSION_TOO_LONG:
   104         case ERROR_META_EXPANSION_TOO_LONG:
   103             err = "Filename too big";
   105             err = "Filename too big";
   104             break;
   106             break;
   105 
   107 
   106         case ERROR_TOO_MANY_HANDLES:
   108         case ERROR_TOO_MANY_HANDLES:
   107         case ERROR_TOO_OPEN_FILES:
   109         case ERROR_TOO_MANY_OPEN_FILES:
   108         case ERROR_NO_MORE_SEARCH_HANDLES:
   110         case ERROR_NO_MORE_SEARCH_HANDLES:
   109             err = "Too many open handles";
   111             err = "Too many open handles";
   110             break;
   112             break;
   111 
   113 
   112         case ERROR_SEEK_ON_DEVICE:
   114         case ERROR_SEEK_ON_DEVICE:
   190 
   192 
   191         case ERROR_EA_LIST_INCONSISTENT:
   193         case ERROR_EA_LIST_INCONSISTENT:
   192             err = "OS/2 reported an inconsistent Extended Attribute list";
   194             err = "OS/2 reported an inconsistent Extended Attribute list";
   193             break;
   195             break;
   194 
   196 
   195         case ERROR_EA_VALUE_UNSUPPORTABLE:
       
   196             err = "OS/2 reported an unsupportable Extended Attribute value";
       
   197             break;
       
   198 
       
   199         case ERROR_SEM_OWNER_DIED:
   197         case ERROR_SEM_OWNER_DIED:
   200             err = "OS/2 reported that semaphore owner died";
   198             err = "OS/2 reported that semaphore owner died";
   201             break;
   199             break;
   202 
   200 
   203         case ERROR_TOO_MANY_SEM_REQUESTS:
   201         case ERROR_TOO_MANY_SEM_REQUESTS:
   228 
   226 
   229 int __PHYSFS_platformInit(void)
   227 int __PHYSFS_platformInit(void)
   230 {
   228 {
   231     char buf[CCHMAXPATH];
   229     char buf[CCHMAXPATH];
   232     APIRET rc;
   230     APIRET rc;
   233     TIB tib;
   231     PTIB ptib;
   234     PIB pib;
   232     PPIB ppib;
   235 
   233 
   236     assert(baseDir == NULL);
   234     assert(baseDir == NULL);
   237 
   235 
   238     BAIL_IF_MACRO(os2err(DosGetInfoBlocks(&tib, &pib)) != NO_ERROR, NULL, 0);
   236     BAIL_IF_MACRO(os2err(DosGetInfoBlocks(&ptib, &ppib)) != NO_ERROR, NULL, 0);
   239     rc = DosQueryModuleName(pib.pib_hmte, sizeof (buf), (PCHAR) buf);
   237     rc = DosQueryModuleName(ppib->pib_hmte, sizeof (buf), (PCHAR) buf);
   240     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, 0);
   238     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, 0);
   241 
   239 
   242     baseDir = (char *) malloc(strlen(buf) + 1);
   240     baseDir = (char *) malloc(strlen(buf) + 1);
   243     BAIL_IF_MACRO(baseDir == NULL, ERR_OUT_OF_MEMORY, 0);
   241     BAIL_IF_MACRO(baseDir == NULL, ERR_OUT_OF_MEMORY, 0);
   244     strcpy(baseDir);
   242     strcpy(baseDir, buf);
   245 
   243 
   246     return(1);  /* success. */
   244     return(1);  /* success. */
   247 } /* __PHYSFS_platformInit */
   245 } /* __PHYSFS_platformInit */
   248 
   246 
   249 
   247 
   275     APIRET rc;
   273     APIRET rc;
   276 
   274 
   277     rc = DosDevIOCtl((HFILE) -1, IOCTL_DISK,
   275     rc = DosDevIOCtl((HFILE) -1, IOCTL_DISK,
   278                      DSK_GETDEVICEPARAMS,
   276                      DSK_GETDEVICEPARAMS,
   279                      &cmd, sizeof (cmd), &ul1,
   277                      &cmd, sizeof (cmd), &ul1,
   280                      &bpb, sizeof (bpb), &u2);
   278                      &bpb, sizeof (bpb), &ul2);
   281 
   279 
   282     /*
   280     /*
   283      * !!! FIXME: Note that this tells us that the media is REMOVABLE...
   281      * !!! FIXME: Note that this tells us that the media is REMOVABLE...
   284      * !!! FIXME:  but it might not be a CD-ROM...check driver name?
   282      * !!! FIXME:  but it might not be a CD-ROM...check driver name?
   285      */
   283      */
   286     return((rc == NO_ERROR) && ((DiskData.fsDeviceAttr & 0x0001) == 0));
   284     return((rc == NO_ERROR) && ((bpb.fsDeviceAttr & 0x0001) == 0));
   287 } /* is_cdrom_drive */
   285 } /* is_cdrom_drive */
   288 
   286 
   289 
   287 
   290 char **__PHYSFS_platformDetectAvailableCDs(void)
   288 char **__PHYSFS_platformDetectAvailableCDs(void)
   291 {
   289 {
   302 
   300 
   303     rc = DosQueryCurrentDisk(&dummy, &drivemap);
   301     rc = DosQueryCurrentDisk(&dummy, &drivemap);
   304     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, retval);
   302     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, retval);
   305 
   303 
   306     /* !!! FIXME: the a, b, and c drives are almost certainly NOT cdroms... */
   304     /* !!! FIXME: the a, b, and c drives are almost certainly NOT cdroms... */
   307     for (i = 0, bit = 1; i < 26; i++, bit << 1)
   305     for (i = 0, bit = 1; i < 26; i++, bit <<= 1)
   308     {
   306     {
   309         if (drivemap & bit)  /* this logical drive exists. */
   307         if (drivemap & bit)  /* this logical drive exists. */
   310         {
   308         {
   311             if ((is_cdrom_drive(i)) && (disc_is_inserted(i)))
   309             if ((is_cdrom_drive(i)) && (disc_is_inserted(i)))
   312             {
   310             {
   429 LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
   427 LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
   430                                                   int omitSymLinks)
   428                                                   int omitSymLinks)
   431 {
   429 {
   432     char spec[CCHMAXPATH];
   430     char spec[CCHMAXPATH];
   433     LinkedStringList *retval = NULL, *p = NULL;
   431     LinkedStringList *retval = NULL, *p = NULL;
   434     FINDFILEBUF3 fb;
   432     FILEFINDBUF3 fb;
   435     HDIR hdir = HDIR_CREATE;
   433     HDIR hdir = HDIR_CREATE;
   436     ULONG count = 1;
   434     ULONG count = 1;
   437     APIRET rc;
   435     APIRET rc;
   438 
   436 
   439     BAIL_IF_MACRO(strlen(dirname) > sizeof (spec) - 4, ERR_OS_ERROR, NULL);
   437     BAIL_IF_MACRO(strlen(dirname) > sizeof (spec) - 4, ERR_OS_ERROR, NULL);
   440     strcpy(spec, dname)
   438     strcpy(spec, dirname);
   441     strcat(spec, "*.*");
   439     strcat(spec, "*.*");
   442 
   440 
   443     rc = DosFindFirst(spec, &hdir,
   441     rc = DosFindFirst(spec, &hdir,
   444                       FILE_DIRECTORY | FILE_ARCHIVED |
   442                       FILE_DIRECTORY | FILE_ARCHIVED |
   445                       FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM,
   443                       FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM,
   446                       &fb, sizeof (fb), &count, FIL_STANDARD)
   444                       &fb, sizeof (fb), &count, FIL_STANDARD);
   447     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, 0);
   445     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, 0);
   448     while (count == 1)
   446     while (count == 1)
   449     {
   447     {
   450         if (strcmp(fb.achName, ".") == 0)
   448         if (strcmp(fb.achName, ".") == 0)
   451             continue;
   449             continue;
   498 
   496 
   499 char *__PHYSFS_platformRealPath(const char *path)
   497 char *__PHYSFS_platformRealPath(const char *path)
   500 {
   498 {
   501     char buf[CCHMAXPATH];
   499     char buf[CCHMAXPATH];
   502     char *retval;
   500     char *retval;
   503     APIRET rc = DosQueryPathInfo(fname, FIL_QUERYFULLNAME, buf, sizeof (buf));
   501     APIRET rc = DosQueryPathInfo(path, FIL_QUERYFULLNAME, buf, sizeof (buf));
   504     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, NULL);
   502     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, NULL);
   505     retval = (char *) malloc(strlen(buf) + 1);
   503     retval = (char *) malloc(strlen(buf) + 1);
   506     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
   504     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
   507     strcpy(retval, buf);
   505     strcpy(retval, buf);
   508     return(retval);
   506     return(retval);
   525      *  DosQueryFileInfo() will fail if we try to get a file length, etc.
   523      *  DosQueryFileInfo() will fail if we try to get a file length, etc.
   526      */
   524      */
   527     os2err(DosOpen(filename, &hfile, &actionTaken, 0, FILE_NORMAL,
   525     os2err(DosOpen(filename, &hfile, &actionTaken, 0, FILE_NORMAL,
   528                    OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
   526                    OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
   529                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
   527                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
   530                    OPEN_FLAGS_NO_INHERIT | OPEN_SHARE_DENYWRITE |
   528                    OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE |
   531                    OPEN_ACCESS_READONLY, NULL));
   529                    OPEN_ACCESS_READONLY, NULL));
   532 
   530 
   533     return((void *) hfile);
   531     return((void *) hfile);
   534 } /* __PHYSFS_platformOpenRead */
   532 } /* __PHYSFS_platformOpenRead */
   535 
   533 
   544      *  DosQueryFileInfo() will fail if we try to get a file length, etc.
   542      *  DosQueryFileInfo() will fail if we try to get a file length, etc.
   545      */
   543      */
   546     os2err(DosOpen(filename, &hfile, &actionTaken, 0, FILE_NORMAL,
   544     os2err(DosOpen(filename, &hfile, &actionTaken, 0, FILE_NORMAL,
   547                    OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
   545                    OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
   548                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
   546                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
   549                    OPEN_FLAGS_NO_INHERIT | OPEN_SHARE_DENYWRITE |
   547                    OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE |
   550                    OPEN_ACCESS_READWRITE, NULL));
   548                    OPEN_ACCESS_READWRITE, NULL));
   551 
   549 
   552     return((void *) hfile);
   550     return((void *) hfile);
   553 } /* __PHYSFS_platformOpenWrite */
   551 } /* __PHYSFS_platformOpenWrite */
   554 
   552 
   555 
   553 
   556 void *__PHYSFS_platformOpenAppend(const char *filename)
   554 void *__PHYSFS_platformOpenAppend(const char *filename)
   557 {
   555 {
   558     ULONG dummy = 0;
   556     ULONG dummy = 0;
   559     HFILE hfile = NULLHANDLE;
   557     HFILE hfile = NULLHANDLE;
       
   558     APIRET rc;
   560 
   559 
   561     /*
   560     /*
   562      * File must be opened SHARE_DENYWRITE and ACCESS_READWRITE, otherwise
   561      * File must be opened SHARE_DENYWRITE and ACCESS_READWRITE, otherwise
   563      *  DosQueryFileInfo() will fail if we try to get a file length, etc.
   562      *  DosQueryFileInfo() will fail if we try to get a file length, etc.
   564      */
   563      */
   565     rc = os2err(DosOpen(filename, &hfile, &dummy, 0, FILE_NORMAL,
   564     rc = os2err(DosOpen(filename, &hfile, &dummy, 0, FILE_NORMAL,
   566                    OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
   565                    OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
   567                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
   566                    OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
   568                    OPEN_FLAGS_NO_INHERIT | OPEN_SHARE_DENYWRITE |
   567                    OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE |
   569                    OPEN_ACCESS_READWRITE, NULL));
   568                    OPEN_ACCESS_READWRITE, NULL));
   570 
   569 
   571     if (rc == NO_ERROR)
   570     if (rc == NO_ERROR)
   572     {
   571     {
   573         if (os2err(DosSetFilePtr(hfile, 0, FILE_END, &dummy)) != NO_ERROR)
   572         if (os2err(DosSetFilePtr(hfile, 0, FILE_END, &dummy)) != NO_ERROR)
   588     PHYSFS_sint64 retval;
   587     PHYSFS_sint64 retval;
   589     ULONG br;
   588     ULONG br;
   590 
   589 
   591     for (retval = 0; retval < count; retval++)
   590     for (retval = 0; retval < count; retval++)
   592     {
   591     {
   593         APIRET rc = os2err(DosRead(hfile, buffer, size, &br));
   592         os2err(DosRead(hfile, buffer, size, &br));
   594         if (br < size)
   593         if (br < size)
   595         {
   594         {
   596             DosSetFilePtr(hfile, -bw, FILE_CURRENT, &br); /* try to cleanup. */
   595             DosSetFilePtr(hfile, -br, FILE_CURRENT, &br); /* try to cleanup. */
   597             return(retval);
   596             return(retval);
   598         } /* if */
   597         } /* if */
   599 
   598 
   600         buffer = (void *) ( ((char *) buffer) + size) );
   599         buffer = (void *) ( ((char *) buffer) + size );
   601     } /* for */
   600     } /* for */
   602 
   601 
   603     return(retval);
   602     return(retval);
   604 } /* __PHYSFS_platformRead */
   603 } /* __PHYSFS_platformRead */
   605 
   604 
   611     PHYSFS_sint64 retval;
   610     PHYSFS_sint64 retval;
   612     ULONG bw;
   611     ULONG bw;
   613 
   612 
   614     for (retval = 0; retval < count; retval++)
   613     for (retval = 0; retval < count; retval++)
   615     {
   614     {
   616         APIRET rc = os2err(DosWrite(hfile, buffer, size, &bw));
   615         os2err(DosWrite(hfile, buffer, size, &bw));
   617         if (bw < size)
   616         if (bw < size)
   618         {
   617         {
   619             DosSetFilePtr(hfile, -bw, FILE_CURRENT, &bw); /* try to cleanup. */
   618             DosSetFilePtr(hfile, -bw, FILE_CURRENT, &bw); /* try to cleanup. */
   620             return(retval);
   619             return(retval);
   621         } /* if */
   620         } /* if */
   622 
   621 
   623         buffer = (void *) ( ((char *) buffer) + size) );
   622         buffer = (void *) ( ((char *) buffer) + size );
   624     } /* for */
   623     } /* for */
   625 
   624 
   626     return(retval);
   625     return(retval);
   627 } /* __PHYSFS_platformWrite */
   626 } /* __PHYSFS_platformWrite */
   628 
   627 
   673 } /* __PHYSFS_platformEOF */
   672 } /* __PHYSFS_platformEOF */
   674 
   673 
   675 
   674 
   676 int __PHYSFS_platformFlush(void *opaque)
   675 int __PHYSFS_platformFlush(void *opaque)
   677 {
   676 {
   678     return(os2err(DosResetBuffers((HFILE) opaque) == NO_ERROR));
   677     return(os2err(DosResetBuffer((HFILE) opaque) == NO_ERROR));
   679 } /* __PHYSFS_platformFlush */
   678 } /* __PHYSFS_platformFlush */
   680 
   679 
   681 
   680 
   682 int __PHYSFS_platformClose(void *opaque)
   681 int __PHYSFS_platformClose(void *opaque)
   683 {
   682 {
   694 } /* __PHYSFS_platformDelete */
   693 } /* __PHYSFS_platformDelete */
   695 
   694 
   696 
   695 
   697 PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
   696 PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
   698 {
   697 {
       
   698     PHYSFS_sint64 retval;
   699     struct tm tm;
   699     struct tm tm;
   700     FILESTATUS3 fs;
   700     FILESTATUS3 fs;
   701     APIRET rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs, sizeof (fs));
   701     APIRET rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs, sizeof (fs));
   702     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, -1);
   702     BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, -1);
   703 
   703 
   726 } /* __PHYSFS_platformTimeslice(void) */
   726 } /* __PHYSFS_platformTimeslice(void) */
   727 
   727 
   728 
   728 
   729 PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
   729 PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
   730 {
   730 {
   731     TIB tib;
   731     PTIB ptib;
   732     PIB pib;
   732     PPIB ppib;
   733 
   733 
   734     /*
   734     /*
   735      * Allegedly, this API never fails, but we'll punt and return a
   735      * Allegedly, this API never fails, but we'll punt and return a
   736      *  default value (zero might as well do) if it does.
   736      *  default value (zero might as well do) if it does.
   737      */
   737      */
   738     BAIL_IF_MACRO(os2err(DosGetInfoBlocks(&tib, &pib)) != NO_ERROR, 0, 0);
   738     BAIL_IF_MACRO(os2err(DosGetInfoBlocks(&ptib, &ppib)) != NO_ERROR, 0, 0);
   739     return((PHYSFS_uint64) tib.tib_ordinal);
   739     return((PHYSFS_uint64) ptib->tib_ordinal);
   740 } /* __PHYSFS_platformGetThreadID */
   740 } /* __PHYSFS_platformGetThreadID */
   741 
   741 
   742 
   742 
   743 void *__PHYSFS_platformCreateMutex(void)
   743 void *__PHYSFS_platformCreateMutex(void)
   744 {
   744 {