home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 2.ddi / CLIBSRC3.ZIP / STAT.CAS < prev    next >
Encoding:
Text File  |  1992-06-10  |  8.0 KB  |  244 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - stat.cas
  3.  *
  4.  * function(s)
  5.  *        stat - gets information about open file
  6.  *-----------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *      C/C++ Run Time Library - Version 5.0
  10.  *
  11.  *      Copyright (c) 1987, 1992 by Borland International
  12.  *      All Rights Reserved.
  13.  *
  14.  */
  15.  
  16.  
  17. #pragma inline
  18. #include <asmrules.h>
  19. #include <sys\stat.h>
  20. #include <dos.h>
  21. #include <_io.h>
  22. #include <fcntl.h>
  23. #include <io.h>
  24. #include <errno.h>
  25. #include <stdlib.h>
  26. #include <ctype.h>
  27. #include <string.h>
  28.  
  29. /*-----------------------------------------------------------------------*
  30.  
  31. Name            stat - gets information about open file
  32.  
  33. Usage           #include <sys\stat.h>
  34.                 int stat(char *pathname, struct stat *buff)
  35.  
  36. Prototype in    sys\stat.h
  37.  
  38. Description     Gather statistics about the file named by *pathP and place them
  39.                 in the buffer *bufP.
  40.  
  41.                 It should be noted that on MSDOS this call can return more
  42.                 information about a file than is possible with the fstat()
  43.                 call.  In particular it is possible to get statistics for
  44.                 directories and the time of the file is accessible for DOS
  45.                 versions prior to 3.0.
  46.  
  47.                 Not all of the fields are relevant to MSDOS.  The statistics
  48.                 fields are set thus:
  49.  
  50.                 st_dev          set to -1 if S_IFCHR, else set to drive
  51.                                 holding the file.
  52.                 st_ino          0
  53.                 st_mode         Unix-style bit-set for file access rights
  54.                 st_nlink        1
  55.                 st_uid          0
  56.                 st_gid          0
  57.                 st_rdev         same as st_dev
  58.                 st_size         file size (0 if S_IFDIR or S_IFCHR)
  59.                 st_atime        time file last changed (seconds since 1970)
  60.                 st_mtime        same as st_atime
  61.                 st_ctime        same as st_atime
  62.  
  63.                 The file access rights bit-set may contain S_IFCHR, S_IFDIR,
  64.                 S_IFREG, S_IREAD, S_IWRITE, or S_IEXEC.
  65.  
  66.                 If the name is for a device, the time fields will be zero
  67.                 and the size field is undefined.
  68.  
  69. Return value    The return value is 0 if the call was successful, otherwise
  70.                 -1 is returned and errno contains the reason.  The buffer
  71.                 is not touched unless the call is successful.
  72.  
  73. *------------------------------------------------------------------------*/
  74. int _FARFUNC stat (const char *pathP, struct stat *bufP)
  75.  
  76. {
  77.     dosSearchInfo       info;
  78.     int                 doserr;
  79.     char                *full;
  80.  
  81.         pushDS_
  82. #if LDATA
  83. asm     push    SS
  84. asm     pop     DS
  85. #endif
  86. asm     lea     dx, info
  87. asm     mov     ah, 1Ah                 /* set Device Transfer Address  */
  88. asm     int     21h
  89.         popDS_
  90. asm     jc      statFailed
  91.  
  92.         pushDS_
  93. asm     LDS_    dx, pathP
  94. asm     mov     cx, 16h      /* include directory, hidden, and system files */
  95. asm     mov     ah, 4Eh      /* Find First      */
  96. asm     int     21h
  97.         popDS_
  98. asm     jc      statFailed
  99. asm     jmp     statOK
  100.  
  101.         /*      Arrive here if MSDOS calls failed.      */
  102. statFailed:
  103.  
  104.     /* Check for the special case where the file is actually the
  105.      * root directory.  Make up a fake dosSearchInfo block for it.
  106.      */
  107.     doserr = _AX;   /* save DOS error code */
  108.     if (strpbrk(pathP,"\\/.") != NULL
  109.         && (full = _fullpath((char *)NULL,pathP,0)) != NULL)
  110.     {
  111.         int drive, lastc;
  112.  
  113.         drive = full[0];
  114.         lastc = full[3];
  115.         if (lastc == '\0')    /* it's a name like "C:\" (i.e. root) */
  116.         {
  117.             free(full);             /* free the full path */
  118.             info.ds_drive = drive - (drive >= 'a' && drive <= 'z' ? 'a' : 'A');
  119.             info.ds_time = 0;       /* 00:00:00 */
  120.             info.ds_date = 0x21;    /* Jan 1 1980 */
  121.             info.ds_size = 0;
  122.             _SI = S_IREAD | S_IFDIR | S_IEXEC;
  123.             goto sta_convertTime;
  124.         }
  125.         else
  126.         {
  127.             /* Try find-file again with the path returned by _fullpath,
  128.              * which doesn't have an ending slash that DOS doesn't like.
  129.              */
  130.             pushDS_
  131. asm         LDS_    dx, full
  132. asm         mov     cx, 16h         /* include directory, hidden, system */
  133. asm         mov     ah, 4Eh         /* Find First      */
  134. asm         int     21h
  135.             popDS_
  136. asm         pushf                   /* save result of find first */
  137.  
  138.             free(full);             /* free the full path */
  139.  
  140. asm         popf                    /* get result of find first */
  141. asm         jnc     statOK
  142.         }
  143.  
  144.     }
  145.     return __IOerror (doserr);
  146.  
  147.  
  148. statOK:
  149.     /* A network drive gives a weird drive number.  In that case,
  150.      * parse the filename to figure out the drive number.
  151.      */
  152.     if ((info.ds_attrib & 0x40) == 0 && info.ds_drive > 26)
  153.     {
  154.         if ((full = _fullpath((char *)NULL,pathP,0)) != NULL)
  155.             info.ds_drive = full[0] + 1
  156.                           - (full[0] >= 'a' && full[0] <= 'z' ? 'a' : 'A');
  157.     }
  158.  
  159. asm     mov     dl, info.ds_attrib
  160. asm     sub     si, si                  /* SI = file mode       */
  161. /*
  162.   It is a non-documented feature of the FindFirst function that devices
  163.   can be "found".  They are distinguished by the attribute 40h.
  164. */
  165. asm     test    dl, 40h                 /* is it a character stream ?   */
  166. asm     jnz     sta_isDevice
  167.  
  168.         /*      Arrive here if the info is for a regular file.  */
  169.  
  170.     _SI |= S_IREAD;
  171. asm     dec     BY0(info.ds_drive)      /* drives from 0..n-1, not 1..n */
  172. asm     test    dl, 10h                 /* directory ?  */
  173. asm     jnz     sta_isDir
  174.  
  175.     _SI |= S_IFREG | S_IREAD;
  176. asm     test    dl, 1                   /* read only ?  */
  177. asm     jnz     sta_convertTime
  178.     _SI |= S_IWRITE;            /* write allowed        */
  179. asm     jmp     short   sta_convertTime
  180.  
  181. sta_isDir:
  182.     _SI |= S_IFDIR | S_IEXEC;
  183.  
  184. /*
  185.   MSDOS time is a 32-bit record, which must be converted into the Unix
  186.   style of seconds since 1970.
  187. */
  188. sta_convertTime:
  189.     __DOStimeToU (*((long *) &info.ds_time));
  190. asm     xchg    cx, ax                  /* result in DX:CX */
  191. asm     jmp     short   sta_construct
  192.  
  193. /* Arrive here if FindFirst identified the name as a character device. */
  194.  
  195. sta_isDevice:
  196. asm     mov     W0 (info.ds_drive), -1
  197.     _SI |= S_IFCHR | S_IREAD | S_IWRITE;
  198. asm     sub     cx, cx
  199. asm     mov     dx, cx                  /* zero time    */
  200.  
  201. /* Arrive here with SI = mode, DX:CX = time, and info = directory info. */
  202.  
  203. sta_construct:
  204. asm     LES_    di, bufP
  205. #if (! LDATA)
  206. asm     push    DS
  207. asm     pop     ES
  208. #endif
  209. asm     cld
  210. asm     mov     al, info.ds_drive
  211. asm     cbw
  212. asm     stosw                   /* device       */
  213. asm     xchg    bx, ax          /* keep a copy  */
  214. asm     sub     ax, ax
  215. asm     stosw                   /* inode        */
  216. asm     xchg    ax, si
  217. asm     stosw                   /* mode */
  218. asm     mov     ax, 1
  219. asm     stosw                   /* number of links      */
  220. asm     xchg    ax, si          /* bring back the zero  */
  221. asm     stosw                   /* user (owner) id      */
  222. asm     stosw                   /* group id     */
  223. asm     xchg    ax, bx
  224. asm     stosw                   /* real device  */
  225. asm     mov     ax, W0 (info.ds_size)
  226. asm     stosw                   /* file..       */
  227. asm     mov     ax, W1 (info.ds_size)
  228. asm     stosw                   /*   ..size     */
  229. asm     xchg    ax, cx
  230. asm     stosw
  231. asm     xchg    ax, dx
  232. asm     stosw                   /* access time          */
  233. asm     xchg    ax, dx
  234. asm     stosw
  235. asm     xchg    ax, dx
  236. asm     stosw                   /* modification time    */
  237. asm     xchg    ax, dx
  238. asm     stosw
  239. asm     xchg    ax, dx
  240. asm     stosw                   /* status change time   */
  241.  
  242.     return 0;
  243. }
  244.