home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 December / VPR9712A.ISO / OLS / OS2 / LHA2P205 / LHA2P205.LZH / lha2-2.05pre / source.lzh / src / port2.c < prev    next >
C/C++ Source or Header  |  1996-02-25  |  28KB  |  1,133 lines

  1. /*
  2.  * port2.c --- LHA OS/2 HPFS version porting library
  3.  *   Copyright (C) 1991-1996, Satoshi HIRAMATSU.
  4.  *
  5.  * $Log$
  6.  */
  7.  
  8.  
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <errno.h>
  14. #include <string.h>
  15. #include <time.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18. #include <direct.h>
  19. #include <ctype.h>
  20. #include "port2.h"
  21. #include "typedef.h"
  22. #include "lh.h"
  23.  
  24.  
  25. #ifdef __API16__
  26. USHORT __version__ = 1000;    /* First version.  */
  27. #endif
  28. int ifs;            /* Installable File System Type */
  29.  
  30.  
  31. unsigned char *
  32. jstrlwr(unsigned char *s)
  33. {
  34.   unsigned char *p = s;
  35.  
  36.   while(*p)
  37.     {
  38.       if(iskanji(*p) && *(p + 1))
  39.     ++p;
  40.       else
  41.     *p = isupper(*p) ? _tolower(*p) : *p;
  42.       ++p;
  43.     }
  44.  
  45.   return s;
  46. }
  47.  
  48. unsigned char *
  49. jstrupr(unsigned char *s)
  50. {
  51.   unsigned char *p = s;
  52.  
  53.   while(*p)
  54.     {
  55.       if(iskanji(*p) && *(p + 1))
  56.     ++p;
  57.       else
  58.     *p = islower(*p) ? _toupper(*p) : *p;
  59.       ++p;
  60.     }
  61.  
  62.   return s;
  63. }
  64.  
  65. #if defined(__IBMC__) || defined(__IBMCPP__)
  66. /*
  67.  * Replace a fopen() library function.
  68.  * Beacuse, IBM C Set++ and IBM VisualAge C++ have a BUG in fopen().
  69.  */
  70. #ifndef _IMPORT
  71. #define _IMPORT
  72. #endif
  73. #ifndef _LNK_CONV
  74. #define _LNK_CONV
  75. #endif
  76.  
  77. FILE * _IMPORT _LNK_CONV
  78. fopen(const char *path, const char *mode)
  79. {
  80.   int id;
  81.  
  82.   switch(*mode)
  83.     {
  84.     case 'r':
  85.       if(strchr(mode, '+'))
  86.     id = open(path, O_RDWR);
  87.       else
  88.     id = open(path, O_RDONLY);
  89.       break;
  90.  
  91.     case 'w':
  92.       id = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  93.       break;
  94.  
  95.     case 'a':
  96.       id = open(path, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
  97.       break;
  98.  
  99.     default:
  100.       return (FILE *)NULL;
  101.     }
  102.  
  103.   if(id < 0)
  104.     return (FILE *)NULL;
  105.  
  106.   return fdopen(id, mode);
  107. }
  108. #endif /* __IBMC__ || __IBMCPP__ */
  109.  
  110.  
  111. #ifdef __SUPPORT_EA__
  112. static char pathname[MAXPATHLEN];
  113.  
  114. static void
  115. SetPathname(const char *path)
  116. {
  117.   char *sep1, *sep2, *null;
  118.  
  119.   strcpy(pathname, path);
  120.   null = pathname;
  121.  
  122.   sep1 = strrchr(path, '\\');
  123.   if((sep2 = strrchr(path, '/')) == (char *)NULL)
  124.     sep2 = strrchr(path, ':');
  125.   if(sep1 == (char *)NULL && sep2 == (char *)NULL)
  126.     {
  127.       *null = '\0';
  128.       return;
  129.     }
  130.  
  131.   null = pathname + ((sep1 > sep2 ? sep1 : sep2) - path) + 1;
  132.   *null = '\0';
  133. }
  134.  
  135.  
  136. static void
  137. BackPath(void)
  138. {
  139.   char *sep1, *sep2, *null;
  140.   register int len;
  141.  
  142.   if(!(len = strlen(pathname)))
  143.     return;
  144.   null = pathname + len - 1;
  145.   *null = '\0';
  146.  
  147.   sep1 = strrchr(pathname, '\\');
  148.   if((sep2 = strrchr(pathname, '/')) == (char *)NULL)
  149.     sep2 = strrchr(pathname, ':');
  150.   if(sep1 == (char *)NULL && sep2 == (char *)NULL)
  151.     {
  152.       *pathname = '\0';
  153.       return;
  154.     }
  155.  
  156.   null = (sep1 > sep2 ? sep1 : sep2) + 1;
  157.   *null = '\0';
  158. }
  159.  
  160.  
  161. static FEA2LIST *
  162. GetEA(const char *path, unsigned long easize)
  163. {
  164.   ULONG ec = -1L, saveec;    /* EA count */
  165.   DENA2 *dena2, *dena2Base;
  166.   EAOP2 eaop2;
  167.   GEA2 *gea2;
  168.   GEA2LIST *gea2list;
  169.   FEA2LIST *fea2list;
  170.   size_t listsize;        /* for calculate next EA offset */
  171.  
  172. #ifdef __DEBUG__
  173.   FEA2 *fea2;
  174.  
  175.   printf("\nFilename = %s\n", path);
  176.   printf("EA size = %ld\n", easize);
  177. #endif
  178.  
  179.   /* Allocte EA buffer */
  180.   listsize = easize + sizeof(DENA2);
  181. #if 0
  182.   listsize = (listsize/4 + (listsize%4 ? 1 : 0))*4;
  183. #else
  184.   listsize = ((listsize >> 2) + ((listsize & 0x03) ? 1 : 0)) << 2;
  185. #endif
  186.   dena2 = (DENA2 *)e_malloc(listsize);
  187.   dena2Base = dena2;        /* save base address */
  188.   fea2list = (FEA2LIST *)dena2;
  189.   if(DosEnumAttribute(ENUMEA_REFTYPE_PATH, (PVOID)path, 1L,
  190.            (PVOID)dena2, easize, &ec, ENUMEA_LEVEL_NO_VALUE))
  191.     {
  192.       free(dena2);
  193.       return (FEA2LIST *)NULL;
  194.     }
  195.  
  196. #ifdef __DEBUG__
  197.   printf("EA num = %ld\n", ec);
  198. #endif
  199.  
  200.   if(!ec)            /* Nothing EA */
  201.     {
  202.       free(dena2);
  203.       return (FEA2LIST *)NULL;
  204.     }
  205.   saveec = ec;
  206.  
  207.   listsize = ec*sizeof(GEA2);    /* Fixed buffer size */
  208.   do
  209.     {
  210. #ifdef __DEBUG__
  211.       printf("Next EA offset = %ld\n", dena2->oNextEntryOffset);
  212.       printf("EA name length = %d\n", dena2->cbName);
  213.       printf("EA value length = %d\n", dena2->cbValue);
  214.       printf("EA name = %s\n\n", dena2->szName);
  215. #endif
  216.  
  217.       listsize += dena2->cbName + 1; /* NULL文字の領域を足す */
  218.       /* DWORD alignment */
  219. #if 0
  220.       listsize = (listsize/4 + (listsize%4 ? 1 : 0))*4;
  221. #else
  222.       listsize = ((listsize >> 2) + ((listsize & 0x03) ? 1 : 0)) << 2;
  223. #endif
  224.  
  225.       /* Set next EA entry address */
  226.       dena2 = (DENA2 *)((ULONG)dena2 + dena2->oNextEntryOffset);
  227.     }
  228.   while(--ec);
  229.  
  230. #ifdef __DEBUG__
  231.   printf("GEA2LIST size = %d\n", listsize);
  232. #endif
  233.  
  234.   /* Allocate GEA2 buffer (add offset entry) */
  235.   gea2list = (GEA2LIST *)e_malloc(sizeof(ULONG) + listsize);
  236.   gea2list->cbList = listsize;    /* set total buffer size */
  237.   ec = saveec;            /* reset EA counter */
  238.   dena2 = dena2Base;        /* reset base address */
  239.   /* set gea2 base address */
  240.   gea2 = (GEA2 *)((ULONG)gea2list + sizeof(ULONG));
  241.   do
  242.     {
  243.       /* calculate next EA offset */
  244.       listsize = sizeof(GEA2) + dena2->cbName;
  245.       /* DWORD alignment */
  246. #if 0
  247.       listsize = (listsize/4 + (listsize%4 ? 1 : 0))*4;
  248. #else
  249.       listsize = ((listsize >> 2) + ((listsize & 0x03) ? 1 : 0)) << 2;
  250. #endif
  251.  
  252.       /* set GEA2 information */
  253.       gea2->oNextEntryOffset = dena2->oNextEntryOffset ? listsize : 0;
  254.       gea2->cbName = dena2->cbName;
  255.       strcpy(gea2->szName, dena2->szName);
  256.  
  257.       /* set next EA entry address */
  258.       dena2 = (DENA2 *)((ULONG)dena2 + dena2->oNextEntryOffset);
  259.       gea2 = (GEA2 *)((ULONG)gea2 + gea2->oNextEntryOffset);
  260.     }
  261.   while(--ec);
  262.  
  263.   /* set EAOP2 */
  264.   eaop2.fpGEA2List = gea2list;
  265.   eaop2.fpFEA2List = fea2list;
  266.   fea2list->cbList = easize;
  267.   /* Get EA */
  268.   if(DosQueryPathInfo((PSZ)path, FIL_QUERYEASFROMLIST, (PVOID)&eaop2,
  269.            sizeof(EAOP2)))
  270.     {
  271.       free(gea2list);
  272.       free(fea2list);
  273.       return (FEA2LIST *)NULL;
  274.     }
  275.  
  276. #ifdef __DEBUG__
  277.   ec = saveec;
  278.   fea2 = fea2list->list;
  279.   printf("EA list size = %ld\n", fea2list->cbList);
  280.   do
  281.     {
  282.       printf("Next EA offset = %ld\n", fea2->oNextEntryOffset);
  283.       printf("EA name length = %d\n", fea2->cbName);
  284.       printf("EA value length = %d\n", fea2->cbValue);
  285.       printf("EA name = %s\n\n", fea2->szName);
  286.  
  287.       fea2 = (FEA2 *)((ULONG)fea2 + fea2->oNextEntryOffset);
  288.     }
  289.   while(--ec);
  290. #endif
  291.  
  292.   free(gea2list);
  293.   return fea2list;
  294. }
  295.  
  296.  
  297. unsigned
  298. SetEA(const char *path, FEA2LIST* fea2list)
  299. {
  300.   EAOP2 eaop2;
  301.   APIRET err;
  302.  
  303.   eaop2.fpGEA2List = (GEA2LIST *)NULL;
  304.   eaop2.fpFEA2List = fea2list;
  305.   err = DosSetPathInfo((PSZ)path, FIL_QUERYEASIZE, (PVOID)&eaop2,
  306.                sizeof(EAOP2), DSPI_WRTTHRU);
  307.  
  308.   return err;
  309. }
  310. #endif /* __SUPPORT_EA__ */
  311.  
  312.  
  313. unsigned
  314. _dos_findfirst(const char *path, unsigned attr, struct find_t *buf)
  315. {
  316. #ifdef __API16__
  317.   FILEFINDBUF findbuf;
  318.   USHORT err;
  319. #else
  320.   FILEFINDBUF4 findbuf;
  321.   APIRET err;
  322. #endif
  323. #ifdef __SUPPORT_EA__
  324.   char realname[MAXPATHLEN];
  325. #endif
  326.  
  327.   buf->sc = 1;
  328.   buf->hdir = HDIR_CREATE;
  329. #ifdef __API16__
  330.   if(__version__ < 1020)    /* for OS/2 v1.0 and v1.1. */
  331.     {
  332.       err = DosFindFirst((PSZ)path, &(buf->hdir), attr, &findbuf,
  333.              sizeof(findbuf), &(buf->sc), 0L);
  334.     }
  335.   else
  336.     {
  337.       err = DosFindFirst2((PSZ)path, &(buf->hdir), attr, &findbuf,
  338.               sizeof(findbuf), &(buf->sc), FIL_STANDARD, 0L);
  339.     }
  340. #else
  341.   err = DosFindFirst((PSZ)path, &(buf->hdir), (ULONG)attr, (PVOID)&findbuf,
  342.              sizeof(findbuf), &(buf->sc), FIL_QUERYEASIZE);
  343. #endif
  344.  
  345.   buf->attrib = findbuf.attrFile;
  346.   buf->wr_time = (findbuf.ftimeLastWrite.hours << 11)
  347.     + (findbuf.ftimeLastWrite.minutes << 5)
  348.       + findbuf.ftimeLastWrite.twosecs;
  349.   buf->wr_date = (findbuf.fdateLastWrite.year << 9)
  350.     + (findbuf.fdateLastWrite.month << 5)
  351.       + findbuf.fdateLastWrite.day;
  352.   buf->size = findbuf.cbFileAlloc;
  353.   strcpy(buf->name, findbuf.achName);
  354.   if(err)
  355.     {
  356. #ifdef __SUPPORT_EA__
  357.       buf->ea = (FEA2LIST *)NULL;
  358. #endif
  359.       errno = ENOENT;
  360.       return (unsigned)err;
  361.     }
  362.  
  363. #ifdef __SUPPORT_EA__
  364.   SetPathname(path);
  365.   if(strcmp(findbuf.achName, ".") && strcmp(findbuf.achName, ".."))
  366.     {
  367.       strcat(strcpy(realname, pathname), findbuf.achName);
  368.       buf->ea = GetEA(realname, findbuf.cbList); /* Get EA */
  369.     }
  370.   else
  371.     buf->ea = (FEA2LIST *)NULL;
  372. #endif
  373.  
  374.   return (unsigned)err;
  375. }
  376.  
  377.  
  378. unsigned
  379. _dos_findnext(struct find_t *buf)
  380. {
  381. #ifdef __API16__
  382.   FILEFINDBUF findbuf;
  383.   USHORT err;
  384. #else
  385.   FILEFINDBUF4 findbuf;
  386.   APIRET err;
  387. #endif
  388. #ifdef __SUPPORT_EA__
  389.   char realname[MAXPATHLEN];
  390. #endif
  391.  
  392.   buf->sc = 1;
  393. #ifdef __API16__
  394.   err = DosFindNext(buf->hdir, &findbuf, sizeof(findbuf), &(buf->sc));
  395. #else
  396.   err = DosFindNext(buf->hdir, (PVOID)&findbuf, sizeof(findbuf), &(buf->sc));
  397. #endif
  398.  
  399.   buf->attrib = findbuf.attrFile;
  400.   buf->wr_time = (findbuf.ftimeLastWrite.hours << 11)
  401.     + (findbuf.ftimeLastWrite.minutes << 5)
  402.       + findbuf.ftimeLastWrite.twosecs;
  403.   buf->wr_date = (findbuf.fdateLastWrite.year << 9)
  404.     + (findbuf.fdateLastWrite.month << 5)
  405.       + findbuf.fdateLastWrite.day;
  406.   buf->size = findbuf.cbFileAlloc;
  407.   strcpy(buf->name, findbuf.achName);
  408.   if(err)
  409.     {
  410. #ifdef __SUPPORT_EA__
  411.       BackPath();
  412.       buf->ea = (FEA2LIST *)NULL;
  413. #endif
  414.       errno = ENOENT;
  415.       return (unsigned)err;
  416.     }
  417.  
  418. #ifdef __SUPPORT_EA__
  419.   if(strcmp(findbuf.achName, ".") && strcmp(findbuf.achName, ".."))
  420.     {
  421.       strcat(strcpy(realname, pathname), findbuf.achName);
  422.       buf->ea = GetEA(realname, findbuf.cbList); /* Get EA */
  423.     }
  424.   else
  425.     buf->ea = (FEA2LIST *)NULL;
  426. #endif
  427.  
  428.   return (unsigned)err;
  429. }
  430.  
  431.  
  432. #ifndef __SUPPORT_CTIME_ATIME__
  433. unsigned
  434. _dos_getftime(int handle, unsigned *date, unsigned *time)
  435. {
  436. #ifdef __API16__
  437.   FILESTATUS filebuf;
  438.  
  439.   if(DosQFileInfo((HFILE)handle, FIL_STANDARD, (PBYTE)&filebuf,
  440.           sizeof(filebuf)))
  441.     {
  442.       errno = EBADF;
  443.       return 1;
  444.     }
  445. #else
  446.   FILESTATUS3 filebuf;
  447.  
  448.   if(DosQueryFileInfo((HFILE)handle, FIL_STANDARD, (PVOID)&filebuf,
  449.               sizeof(filebuf)))
  450.     {
  451.       errno = EBADF;
  452.       return 1;
  453.     }
  454. #endif
  455.  
  456.   *time = (filebuf.ftimeLastWrite.hours << 11)
  457.     + (filebuf.ftimeLastWrite.minutes << 5)
  458.       + filebuf.ftimeLastWrite.twosecs;
  459.   *date = (filebuf.fdateLastWrite.year << 9)
  460.     + (filebuf.fdateLastWrite.month << 5)
  461.       + filebuf.fdateLastWrite.day;
  462.   *time &= 0xffff;
  463.   *date &= 0xffff;
  464.  
  465.   return 0;
  466. }
  467. #else
  468. unsigned
  469. _os2_getftime(int handle, time_t *mod, time_t *cre, time_t *acc)
  470. {
  471.   FILESTATUS3 filebuf;
  472.   union stamp stamp;
  473.  
  474.   if(DosQueryFileInfo((HFILE)handle, FIL_STANDARD, (PVOID)&filebuf,
  475.               sizeof(filebuf)))
  476.     {
  477.       errno = EBADF;
  478.       return 1;
  479.     }
  480.  
  481.   stamp.t.time = (filebuf.ftimeLastWrite.hours << 11)
  482.     + (filebuf.ftimeLastWrite.minutes << 5)
  483.       + filebuf.ftimeLastWrite.twosecs;
  484.   stamp.t.date = (filebuf.fdateLastWrite.year << 9)
  485.     + (filebuf.fdateLastWrite.month << 5)
  486.       + filebuf.fdateLastWrite.day;
  487.   stamp.t.time &= 0xffff;
  488.   stamp.t.date &= 0xffff;
  489.   *mod = dos2unix(&stamp.s);
  490.  
  491.   stamp.t.time = (filebuf.ftimeCreation.hours << 11)
  492.     + (filebuf.ftimeCreation.minutes << 5)
  493.       + filebuf.ftimeCreation.twosecs;
  494.   stamp.t.date = (filebuf.fdateCreation.year << 9)
  495.     + (filebuf.fdateCreation.month << 5)
  496.       + filebuf.fdateCreation.day;
  497.   stamp.t.time &= 0xffff;
  498.   stamp.t.date &= 0xffff;
  499.   *cre = dos2unix(&stamp.s);
  500.  
  501.   stamp.t.time = (filebuf.ftimeLastAccess.hours << 11)
  502.     + (filebuf.ftimeLastAccess.minutes << 5)
  503.       + filebuf.ftimeLastAccess.twosecs;
  504.   stamp.t.date = (filebuf.fdateLastAccess.year << 9)
  505.     + (filebuf.fdateLastAccess.month << 5)
  506.       + filebuf.fdateLastAccess.day;
  507.   stamp.t.time &= 0xffff;
  508.   stamp.t.date &= 0xffff;
  509.   *acc = dos2unix(&stamp.s);
  510.  
  511.   return 0;
  512. }
  513. #endif
  514.  
  515.  
  516. unsigned
  517. _dos_getdtime(char *path, unsigned *date, unsigned *time)
  518. {
  519. #ifdef __API16__
  520.   FILESTATUS filebuf;
  521.  
  522.   if(DosQPathInfo((PSZ)path, FIL_STANDARD, (PBYTE)&filebuf,
  523.           sizeof(filebuf), 0L))
  524.     {
  525.       errno = EBADF;
  526.       return 1;
  527.     }
  528. #else
  529.   FILESTATUS3 filebuf;
  530.  
  531.   if(DosQueryPathInfo((PSZ)path, FIL_STANDARD, (PVOID)&filebuf,
  532.               sizeof(filebuf)))
  533.     {
  534.       errno = EBADF;
  535.       return 1;
  536.     }
  537. #endif
  538.  
  539.   *time = (filebuf.ftimeLastWrite.hours << 11)
  540.     + (filebuf.ftimeLastWrite.minutes << 5)
  541.       + filebuf.ftimeLastWrite.twosecs;
  542.   *date = (filebuf.fdateLastWrite.year << 9)
  543.     + (filebuf.fdateLastWrite.month << 5)
  544.       + filebuf.fdateLastWrite.day;
  545.   *time &= 0xffff;
  546.   *date &= 0xffff;
  547.  
  548.   return 0;
  549. }
  550.  
  551.  
  552. time_t
  553. getdirectorytime(const char *f)
  554. {
  555.   union stamp stamp;
  556.   char p[MAXPATHLEN];
  557.   int namlen;
  558.   unsigned date, time;
  559.  
  560.   namlen = strlen(f) - 1;
  561.   if(*(f + namlen) == '/')
  562.     {
  563.       strncpy(p, f, namlen);
  564.       p[namlen] = '\0';
  565.     }
  566.   else
  567.     strcpy(p, f);
  568.  
  569.   _dos_getdtime(p, &date, &time);
  570.   stamp.t.date = date & 0xffff;
  571.   stamp.t.time = time & 0xffff;
  572.  
  573.   return dos2unix(&stamp.s);
  574. }
  575.  
  576.  
  577. #ifndef __SUPPORT_CTIME_ATIME__
  578. unsigned
  579. _dos_setftime(int handle, unsigned date, unsigned time)
  580. {
  581. #ifdef __API16__
  582.   FILESTATUS filebuf;
  583. #else
  584.   FILESTATUS3 filebuf;
  585.  
  586.   date &= 0xffff;
  587.   time &= 0xffff;
  588. #endif
  589.   filebuf.ftimeLastWrite.hours = 0x1f & (time >> 11);
  590.   filebuf.ftimeLastWrite.minutes = 0x3f & (time >> 5);
  591.   filebuf.ftimeLastWrite.twosecs = 0x1f & time;
  592.   filebuf.fdateLastWrite.year = 0x1f & (date >> 9);
  593.   filebuf.fdateLastWrite.month = 0x0f & (date >> 5);
  594.   filebuf.fdateLastWrite.day = 0x7f & date;
  595.   filebuf.ftimeLastAccess.hours = filebuf.ftimeLastWrite.hours;
  596.   filebuf.ftimeLastAccess.minutes = filebuf.ftimeLastWrite.minutes;
  597.   filebuf.ftimeLastAccess.twosecs = filebuf.ftimeLastWrite.twosecs;
  598.   filebuf.fdateLastAccess.year = filebuf.fdateLastWrite.year;
  599.   filebuf.fdateLastAccess.month = filebuf.fdateLastWrite.month;
  600.   filebuf.fdateLastAccess.day = filebuf.fdateLastWrite.day;
  601.   filebuf.ftimeCreation.hours = filebuf.ftimeLastWrite.hours;
  602.   filebuf.ftimeCreation.minutes = filebuf.ftimeLastWrite.minutes;
  603.   filebuf.ftimeCreation.twosecs = filebuf.ftimeLastWrite.twosecs;
  604.   filebuf.fdateCreation.year = filebuf.fdateLastWrite.year;
  605.   filebuf.fdateCreation.month = filebuf.fdateLastWrite.month;
  606.   filebuf.fdateCreation.day = filebuf.fdateLastWrite.day;
  607.   filebuf.cbFile = 0L;
  608.   filebuf.cbFileAlloc = 0L;
  609.   filebuf.attrFile = 0;
  610. #ifdef __API16__
  611.   if(DosSetFileInfo((HFILE)handle, 0x0001, (PBYTE)&filebuf, sizeof(filebuf)))
  612.     {
  613.       errno = EBADF;
  614.       return 1;
  615.     }
  616. #else
  617.   if(DosSetFileInfo((HFILE)handle, FIL_STANDARD, (PVOID)&filebuf,
  618.             sizeof(filebuf)))
  619.     {
  620.       errno = EBADF;
  621.       return 1;
  622.     }
  623. #endif
  624.  
  625.   return 0;
  626. }
  627. #else
  628. unsigned
  629. _os2_setftime(int handle, time_t *t_mod, time_t *t_cre, time_t *t_acc)
  630. {
  631.   FILESTATUS3 filebuf;
  632.   union stamp mod, cre, acc;
  633.  
  634.   mod.s = *unix2dos(*t_mod);
  635.   if(t_cre)
  636.     cre.s = *unix2dos(*t_cre);
  637.   else
  638.     cre.t.time = cre.t.date = 0;
  639.   if(t_acc)
  640.     acc.s = *unix2dos(*t_acc);
  641.   else
  642.     acc.t.time = acc.t.date = 0;
  643.  
  644.   mod.t.time &= 0xffff;
  645.   mod.t.date &= 0xffff;
  646.   filebuf.ftimeLastWrite.hours = 0x1f & (mod.t.time >> 11);
  647.   filebuf.ftimeLastWrite.minutes = 0x3f & (mod.t.time >> 5);
  648.   filebuf.ftimeLastWrite.twosecs = 0x1f & mod.t.time;
  649.   filebuf.fdateLastWrite.year = 0x1f & (mod.t.date >> 9);
  650.   filebuf.fdateLastWrite.month = 0x0f & (mod.t.date >> 5);
  651.   filebuf.fdateLastWrite.day = 0x7f & mod.t.date;
  652.  
  653.   cre.t.time &= 0xffff;
  654.   cre.t.date &= 0xffff;
  655.   filebuf.ftimeCreation.hours = 0x1f & (cre.t.time >> 11);
  656.   filebuf.ftimeCreation.minutes = 0x3f & (cre.t.time >> 5);
  657.   filebuf.ftimeCreation.twosecs = 0x1f & cre.t.time;
  658.   filebuf.fdateCreation.year = 0x1f & (cre.t.date >> 9);
  659.   filebuf.fdateCreation.month = 0x0f & (cre.t.date >> 5);
  660.   filebuf.fdateCreation.day = 0x7f & cre.t.date;
  661.  
  662.   acc.t.time &= 0xffff;
  663.   acc.t.date &= 0xffff;
  664.   filebuf.ftimeLastAccess.hours = 0x1f & (acc.t.time >> 11);
  665.   filebuf.ftimeLastAccess.minutes = 0x3f & (acc.t.time >> 5);
  666.   filebuf.ftimeLastAccess.twosecs = 0x1f & acc.t.time;
  667.   filebuf.fdateLastAccess.year = 0x1f & (acc.t.date >> 9);
  668.   filebuf.fdateLastAccess.month = 0x0f & (acc.t.date >> 5);
  669.   filebuf.fdateLastAccess.day = 0x7f & acc.t.date;
  670.  
  671.   filebuf.cbFile = 0L;
  672.   filebuf.cbFileAlloc = 0L;
  673.   filebuf.attrFile = 0;
  674.  
  675.   if(DosSetFileInfo((HFILE)handle, FIL_STANDARD, (PVOID)&filebuf,
  676.             sizeof(filebuf)))
  677.     {
  678.       errno = EBADF;
  679.       return 1;
  680.     }
  681.  
  682.   return 0;
  683. }
  684. #endif
  685.  
  686.  
  687. unsigned
  688. _dos_getfileattr(const char *path, unsigned *attr)
  689. {
  690.   char p[MAXPATHLEN];
  691.   int namlen;
  692. #ifndef __API16__
  693.   FILESTATUS3 fileinfo;
  694. #endif
  695.  
  696.   namlen = strlen(path) - 1;
  697.   if(*(path + namlen) == '/')
  698.     {
  699.       strncpy(p, path, namlen);
  700.       p[namlen] = '\0';
  701.     }
  702.   else
  703.     strcpy(p, path);
  704.  
  705. #ifdef __API16__
  706.   if(DosQFileMode((PSZ)p, attr, 0L))
  707.     {
  708.       errno = ENOENT;
  709.       return  1;
  710.     }
  711. #else
  712.   if(DosQueryPathInfo((PSZ)path, FIL_STANDARD, (PVOID)&fileinfo,
  713.               sizeof(fileinfo)))
  714.     return 1;
  715.  
  716.   *attr = (unsigned)fileinfo.attrFile;
  717. #endif
  718.  
  719.   return 0;
  720. }
  721.  
  722.  
  723. unsigned
  724. _dos_setfileattr(const char *path, unsigned attr)
  725. {
  726. #ifdef __API16__
  727.   USHORT result;
  728.  
  729.   result = DosSetFileMode((PSZ)path, attr, 0L);
  730.   switch(result)
  731.     {
  732.     case 108:            /* ERROR_DRIVE_LOCKED */
  733.       errno = EACCES;
  734.       return 1;
  735.  
  736.     default:
  737.       errno = ENOENT;
  738.       return 1;
  739.     }
  740. #else
  741.   FILESTATUS3 fileinfo;
  742.  
  743.   if(DosQueryPathInfo((PSZ)path, FIL_STANDARD, (PVOID)&fileinfo,
  744.               sizeof(fileinfo)))
  745.     return 1;
  746.  
  747.   fileinfo.attrFile = (USHORT)(0xffff & attr);
  748.   DosSetPathInfo((PSZ)path, FIL_STANDARD, (PVOID)&fileinfo,
  749.          sizeof(fileinfo), 0);
  750. #endif
  751.  
  752.   return 0;
  753. }
  754.  
  755.  
  756. unsigned
  757. _dos_getdiskfree(unsigned drv, struct diskfree_t *space)
  758. {
  759.   FSALLOCATE info;
  760.  
  761. #ifdef __API16__
  762.   if(DosQFSInfo(drv, 0x0001, (PBYTE)&info, sizeof(info)))
  763.     {
  764.       errno = EINVAL;
  765.       return 1;
  766.     }
  767. #else
  768.   if(DosQueryFSInfo(drv, FSIL_ALLOC, (PVOID)&info, sizeof(info)))
  769.     {
  770.       errno = EINVAL;
  771.       return 1;
  772.     }
  773. #endif
  774.  
  775.   space->total_clusters = info.cUnit;
  776.   space->avail_clusters = info.cUnitAvail;
  777.   space->sectors_per_cluster = info.cSectorUnit;
  778.   space->bytes_per_sector = info.cbSector;
  779.  
  780.   return 0;
  781. }
  782.  
  783.  
  784. char *
  785. stpcpy(char *dest, const char *src)
  786. {
  787.   strcpy(dest, src);
  788.  
  789.   return (char *)(dest + strlen(src));
  790. }
  791.  
  792.  
  793. char *
  794. mktemp(char *template)
  795. {
  796.   static char prefix[]
  797.     = "0123456789abcdefghijklmnopqrstuvwxyz";
  798.   register size_t tlen, plen;
  799.   register int cnt = 0;
  800.   struct stat statbuf;
  801.   PTIB tib;
  802.   PPIB pib;
  803.  
  804.   if(!template)
  805.     return template;            /* NULL pointer */
  806.  
  807.   if((tlen = strlen(template)) < 6)
  808.     return (char *)NULL;        /* Wrong template string */
  809.  
  810.   if(strcmp(&template[tlen - 6], "XXXXXX"))
  811.     return (char *)NULL;        /* Wrong template string */
  812.  
  813.   DosGetInfoBlocks(&tib, &pib);
  814.   if(sprintf(&template[tlen - 5], "%.5lu", pib->pib_ulpid % 100000) != 5)
  815.     return (char *)NULL;        /* Invalid? PID */
  816.  
  817.   plen = strlen(prefix);
  818.   do
  819.     {
  820.       template[tlen - 6] = prefix[cnt++];
  821.       if(stat(template, &statbuf))
  822.         return template;        /* Cannot find "template".  */
  823.     }
  824.   while(cnt < plen);
  825.  
  826.   return (char *)NULL;            /* Cannot make unique name.  */
  827. }
  828.  
  829.  
  830. static int
  831. CheckLongname(USHORT drvno)
  832. {
  833.   char check[] = "a:.longname.XXXXXX";
  834.   int id;
  835.  
  836.   check[0] = (char)('a' + drvno);
  837.   mktemp(check);
  838.   id = open(check, O_CREAT | O_EXCL | O_WRONLY, S_IWRITE);
  839.   if(id < 0)
  840.     switch(errno)
  841.       {
  842.       case EEXIST:
  843.       case EACCESS:
  844.     return HPFS;
  845.  
  846.       /* case ENOENT: */
  847.       /* case EMFILE: */
  848.       /* case EOS2ERR: */
  849.       default:
  850.     return FAT;
  851.       }
  852.  
  853.   close(id);
  854.   remove(check);
  855.  
  856.   return HPFS;
  857. }
  858.  
  859.  
  860. void
  861. SetFileSystem(int cmd, const char *dir)
  862. {
  863.   PSZ psz;
  864.   char drv[3];
  865.   USHORT Version, drvno;
  866. #ifdef __API16__
  867.   PUSHORT pcb;
  868.   USHORT cb;
  869.   SEL sel;
  870. #else
  871.   BYTE fsinfo[sizeof(FSQBUFFER2) + (3*CCHMAXPATH)];
  872.   ULONG fsinfosize = sizeof(fsinfo);
  873. #endif
  874.  
  875. #ifdef __API16__
  876.   DosGetVersion(&Version);
  877.   __version__ = HIBYTE(Version)*100;
  878.   __version__ += LOBYTE(Version);
  879.   if(__version__ < 1020)
  880.     {
  881.       ifs = FAT;
  882.       return;
  883.     }
  884. #endif
  885.  
  886.   if(!cmd && strlen(dir))    /* extract */
  887.     {
  888.       if(*(dir + 1) == ':')
  889.     drv[0] = *dir;
  890.       else            /* NO have drive information */
  891.     {
  892.       drvno = _getdrive();
  893.       drv[0] = (char)('a' + (--drvno));
  894.     }
  895.     }
  896.   else
  897.     {                /* archive or NO base-directory extract */
  898.       drvno = _getdrive();
  899.       drv[0] = (char)('a' + (--drvno));
  900.     }
  901.   drv[1] = ':';
  902.   drv[2] = '\0';
  903.  
  904. #ifdef __API16__
  905.   DosAllocSeg(128, (PSEL)&sel, SEG_NONSHARED);
  906.   cb = 128;
  907.   DosQFSAttach(&drv[0], 0, FSAIL_QUERYNAME, (PBYTE)MAKEP(sel, 0), &cb, 0L);
  908.   pcb = MAKEP(sel, 2);        /* length of device name */
  909.   psz = MAKEP(sel, 4);        /* device name */
  910.   psz += *pcb + 3;        /* add '\0' and length of divice name */
  911. #else
  912.   DosQueryFSAttach(drv, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)&fsinfo, &fsinfosize);
  913.   psz = ((PFSQBUFFER2)&fsinfo)->szName + ((PFSQBUFFER2)&fsinfo)->cbName + 1;
  914. #endif
  915.  
  916.   if(!strcmp("FAT", psz) || !strcmp("CDFS", psz) || !strcmp("NETWARE", psz))
  917.     ifs = FAT;
  918.   else if(!strcmp("HPFS", psz))
  919.     ifs = HPFS;
  920.   else
  921.     ifs = CheckLongname(drvno);
  922.  
  923.   return;
  924. }
  925.  
  926.  
  927. int
  928. GetFileSystem(const char *name)
  929. {
  930.   PSZ psz;
  931.   char drv[3];
  932.   USHORT Version, drvno;
  933. #ifdef __API16__
  934.   PUSHORT pcb;
  935.   USHORT cb;
  936.   SEL sel;
  937. #else
  938.   BYTE fsinfo[sizeof(FSQBUFFER2) + (3*CCHMAXPATH)];
  939.   ULONG fsinfosize = sizeof(fsinfo);
  940. #endif
  941.  
  942. #ifdef __API16__
  943.   DosGetVersion(&Version);
  944.   __version__ = HIBYTE(Version)*100;
  945.   __version__ += LOBYTE(Version);
  946.   if(__version__ < 1020)
  947.     return FAT;
  948. #endif
  949.  
  950.   if(*(name + 1) == ':')
  951.     drv[0] = *name;
  952.   else                /* NO have drive information */
  953.     {
  954.       drvno = _getdrive();
  955.       drv[0] = (char)('a' + (--drvno));
  956.     }
  957.   drv[1] = ':';
  958.   drv[2] = '\0';
  959. #ifdef __API16__
  960.   DosAllocSeg(128, (PSEL)&sel, SEG_NONSHARED);
  961.   cb = 128;
  962.   DosQFSAttach(&drv[0], 0, FSAIL_QUERYNAME, (PBYTE)MAKEP(sel, 0), &cb, 0L);
  963.   pcb = MAKEP(sel, 2);        /* length of device name */
  964.   psz = MAKEP(sel, 4);        /* device name */
  965.   psz += *pcb + 3;        /* add '\0' and length of divice name */
  966. #else
  967.   DosQueryFSAttach(drv, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)&fsinfo, &fsinfosize);
  968.   psz = ((PFSQBUFFER2)&fsinfo)->szName + ((PFSQBUFFER2)&fsinfo)->cbName + 1;
  969. #endif
  970.  
  971.   if(!strcmp("FAT", psz) || !strcmp("CDFS", psz) || !strcmp("NETWARE", psz))
  972.     return FAT;
  973.   else
  974.     return HPFS;
  975. }
  976.  
  977.  
  978. /* common message pointer */
  979. char *_NOARCNMERR, *_NOFNERR, *_NOARCERR, *_MKTMPERR, *_DUPFNERR, *_TOOLONGERR;
  980. char *_NOFILEERR, *_MKFILEERR, *_RDERR, *_WTERR, *_MEMOVRERR, *_CTRLBRK;
  981. char *_NOMATCHERR, *_NOTLZH, *_SAMEFILE, *_OVERWT, *_MKDIR, *_MKDIRERR;
  982. char *_RDONLY, *_COPYERR, *_BROKENARC, *_MAYDELETE, *_MAYCONT, *_SAMEDIR;
  983. char *_NEWFILE, *_METHODERR, *_DISKFULL, *_NOCRC, *_NOMOREEXT, *_SPECIALATTR;
  984. char *_EXTRADATA;
  985. #if 0
  986. char *_UNKNOWNERR, *_INVCMDERR, *_MANYPATERR, *_RENAMEERR, *_TOOMANYERR;
  987. char *_INVSWERR, *_CRCERR, *_MKARCERR, *_NESTERR;
  988. #endif
  989. #ifndef FIRST_COMPILATION
  990. char *use;
  991. #endif
  992.  
  993.  
  994. /* support code page 437 and 932 */
  995. extern char NOARCNMERR_437[], NOFNERR_437[], NOARCERR_437[], MKTMPERR_437[];
  996. extern char DUPFNERR_437[], TOOLONGERR_437[], NOFILEERR_437[], MKFILEERR_437[];
  997. extern char RDERR_437[], WTERR_437[], MEMOVRERR_437[], CTRLBRK_437[];
  998. extern char NOMATCHERR_437[], NOTLZH_437[], SAMEFILE_437[], OVERWT_437[];
  999. extern char MKDIR_437[], MKDIRERR_437[], RDONLY_437[], COPYERR_437[];
  1000. extern char BROKENARC_437[], MAYDELETE_437[], MAYCONT_437[], SAMEDIR_437[];
  1001. extern char NEWFILE_437[], METHODERR_437[], DISKFULL_437[], NOCRC_437[];
  1002. extern char NOMOREEXT_437[], SPECIALATTR_437[], EXTRADATA_437[];
  1003.  
  1004. extern char NOARCNMERR_932[], NOFNERR_932[], NOARCERR_932[], MKTMPERR_932[];
  1005. extern char DUPFNERR_932[], TOOLONGERR_932[], NOFILEERR_932[], MKFILEERR_932[];
  1006. extern char RDERR_932[], WTERR_932[], MEMOVRERR_932[], CTRLBRK_932[];
  1007. extern char NOMATCHERR_932[], NOTLZH_932[], SAMEFILE_932[], OVERWT_932[];
  1008. extern char MKDIR_932[], MKDIRERR_932[], RDONLY_932[], COPYERR_932[];
  1009. extern char BROKENARC_932[], MAYDELETE_932[], MAYCONT_932[], SAMEDIR_932[];
  1010. extern char NEWFILE_932[], METHODERR_932[], DISKFULL_932[], NOCRC_932[];
  1011. extern char NOMOREEXT_932[], SPECIALATTR_932[], EXTRADATA_932[];
  1012. #if 0
  1013. extern char UNKNOWNERR_437[], INVCMDERR_437[], MANYPATERR_437[];
  1014. extern char RENAMEERR_437[], TOOMANYERR_437[], INVSWERR_437[], CRCERR_437[];
  1015. extern char MKARCERR_437[], NESTERR_437[];
  1016. extern char UNKNOWNERR_932[], INVCMDERR_932[], MANYPATERR_932[];
  1017. extern char RENAMEERR_932[], TOOMANYERR_932[], INVSWERR_932[], CRCERR_932[];
  1018. extern char MKARCERR_932[], NESTERR_932[];
  1019. #endif
  1020.  
  1021.  
  1022. #ifndef FIRST_COMPILATION
  1023. extern char use_e[], use_j[];
  1024. #endif
  1025.  
  1026. void
  1027. SetMessage(void)
  1028. {
  1029. #ifdef __API16__
  1030.   USHORT CodePage = 0, cnt;
  1031. #else
  1032.   ULONG CodePage = 0, cnt;
  1033. #endif
  1034.  
  1035.   DosGetCp(sizeof(CodePage), &CodePage, &cnt);
  1036.   if((CodePage == 932) || (CodePage == 942)) /* JAPANESE */
  1037.     {
  1038.       _NOARCNMERR = NOARCNMERR_932;
  1039.       _NOFNERR = NOFNERR_932;
  1040.       _NOARCERR = NOARCERR_932;
  1041.       _MKTMPERR = MKTMPERR_932;
  1042.       _DUPFNERR = DUPFNERR_932;
  1043.       _TOOLONGERR = TOOLONGERR_932;
  1044.       _NOFILEERR = NOFILEERR_932;
  1045.       _MKFILEERR = MKFILEERR_932;
  1046.       _RDERR = RDERR_932;
  1047.       _WTERR = WTERR_932;
  1048.       _MEMOVRERR = MEMOVRERR_932;
  1049.       _CTRLBRK = CTRLBRK_932;
  1050.       _NOMATCHERR = NOMATCHERR_932;
  1051.       _NOTLZH = NOTLZH_932;
  1052.       _SAMEFILE = SAMEFILE_932;
  1053.       _OVERWT = OVERWT_932;
  1054.       _MKDIR = MKDIR_932;
  1055.       _MKDIRERR = MKDIRERR_932;
  1056.       _RDONLY = RDONLY_932;
  1057.       _COPYERR = COPYERR_932;
  1058.       _BROKENARC = BROKENARC_932;
  1059.       _MAYDELETE = MAYDELETE_932;
  1060.       _MAYCONT = MAYCONT_932;
  1061.       _SAMEDIR = SAMEDIR_932;
  1062.       _NEWFILE = NEWFILE_932;
  1063.       _METHODERR = METHODERR_932;
  1064.       _DISKFULL = DISKFULL_932;
  1065.       _NOCRC = NOCRC_932;
  1066.       _NOMOREEXT = NOMOREEXT_932;
  1067.       _SPECIALATTR = SPECIALATTR_932;
  1068.       _EXTRADATA = EXTRADATA_932;
  1069. #if 0
  1070.       _UNKNOWNERR = UNKNOWNERR_932;
  1071.       _INVCMDERR = INVCMDERR_932;
  1072.       _MANYPATERR = MANYPATERR_932;
  1073.       _RENAMEERR = RENAMEERR_932;
  1074.       _TOOMANYERR = TOOMANYERR_932;
  1075.       _INVSWERR = INVSWERR_932;
  1076.       _CRCERR = CRCERR_932;
  1077.       _MKARCERR = MKARCERR_932;
  1078.       _NESTERR = NESTERR_932;
  1079. #endif
  1080. #ifndef FIRST_COMPILATION
  1081.       use = use_j;
  1082. #endif
  1083.     }
  1084.   else
  1085.     {
  1086.       _NOARCNMERR = NOARCNMERR_437;
  1087.       _NOFNERR = NOFNERR_437;
  1088.       _NOARCERR = NOARCERR_437;
  1089.       _MKTMPERR = MKTMPERR_437;
  1090.       _DUPFNERR = DUPFNERR_437;
  1091.       _TOOLONGERR = TOOLONGERR_437;
  1092.       _NOFILEERR = NOFILEERR_437;
  1093.       _MKFILEERR = MKFILEERR_437;
  1094.       _RDERR = RDERR_437;
  1095.       _WTERR = WTERR_437;
  1096.       _MEMOVRERR = MEMOVRERR_437;
  1097.       _CTRLBRK = CTRLBRK_437;
  1098.       _NOMATCHERR = NOMATCHERR_437;
  1099.       _NOTLZH = NOTLZH_437;
  1100.       _SAMEFILE = SAMEFILE_437;
  1101.       _OVERWT = OVERWT_437;
  1102.       _MKDIR = MKDIR_437;
  1103.       _MKDIRERR = MKDIRERR_437;
  1104.       _RDONLY = RDONLY_437;
  1105.       _COPYERR = COPYERR_437;
  1106.       _BROKENARC = BROKENARC_437;
  1107.       _MAYDELETE = MAYDELETE_437;
  1108.       _MAYCONT = MAYCONT_437;
  1109.       _SAMEDIR = SAMEDIR_437;
  1110.       _NEWFILE = NEWFILE_437;
  1111.       _METHODERR = METHODERR_437;
  1112.       _DISKFULL = DISKFULL_437;
  1113.       _NOCRC = NOCRC_437;
  1114.       _NOMOREEXT = NOMOREEXT_437;
  1115.       _SPECIALATTR = SPECIALATTR_437;
  1116.       _EXTRADATA = EXTRADATA_437;
  1117. #if 0
  1118.       _UNKNOWNERR = UNKNOWNERR_437;
  1119.       _INVCMDERR = INVCMDERR_437;
  1120.       _MANYPATERR = MANYPATERR_437;
  1121.       _RENAMEERR = RENAMEERR_437;
  1122.       _TOOMANYERR = TOOMANYERR_437;
  1123.       _INVSWERR = INVSWERR_437;
  1124.       _CRCERR = CRCERR_437;
  1125.       _MKARCERR = MKARCERR_437;
  1126.       _NESTERR = NESTERR_437;
  1127. #endif
  1128. #ifndef FIRST_COMPILATION
  1129.       use = use_e;
  1130. #endif
  1131.     }
  1132. }
  1133.