home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / dos / lfn / _use_lfn.c next >
Encoding:
C/C++ Source or Header  |  1996-08-31  |  5.2 KB  |  194 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <libc/stubs.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <ctype.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <dos.h>
  10. #include <dpmi.h>
  11. #include <go32.h>
  12. #include <crt0.h>
  13. #include <sys/movedata.h>
  14. #include <libc/bss.h>
  15. #include <libc/environ.h>
  16. #include <libc/farptrgs.h>
  17.  
  18. static int      use_lfn_bss_count = -1;    /* if we are restarted (emacs) */
  19. static unsigned filesystem_flags  = _FILESYS_UNKNOWN;
  20. static unsigned last_env_changed = 0;
  21. static int    last_drive; /* drive *letter*, not *number*! */
  22.  
  23. /* Return the parameters of the filesystem where PATH resides.  */
  24. unsigned
  25. _get_volume_info (const char *path, int *maxfile, int *maxpath, char *fsystype)
  26. {
  27.   __dpmi_regs r;
  28.   unsigned long tbuf_la  = __tb & 0xfffff;
  29.   unsigned long tbuf_seg = tbuf_la >> 4;
  30.   unsigned    retval;
  31.  
  32.   if (path && *path)
  33.   {
  34.     if (path[1] == ':')
  35.     {
  36.       dosmemput (path, 3, tbuf_la);
  37.       tbuf_la += 3;
  38.       if (path[2] != '\\')
  39.     _farpokeb(_dos_ds, tbuf_la - 1, '\\');
  40.       _farpokeb(_dos_ds, tbuf_la++, '\0');
  41.     }
  42.     else if (*path == '\\' && path[1] == '\\')
  43.     {
  44.       int plen = strlen (path) + 1;
  45.  
  46.       /* FIXME: what should we do with the UNC pathnames like
  47.      "\\machine\vol\path"?  We need to know either their
  48.      DOS drive letter or where does the root directory path
  49.      ends.  For now, we assume the entire path is the root path.  */
  50.       dosmemput (path, plen, tbuf_la);
  51.       tbuf_la += plen + 1;
  52.     }
  53.   }
  54.  
  55.   /* No explicit drive, use default drive.  */
  56.   if (tbuf_la == __tb)
  57.   {
  58.     unsigned drv_no;
  59.  
  60.     /* FIXME: can `_dos_getdrive' fail (e.g. no floppy in drive)?  */
  61.     _dos_getdrive(&drv_no);
  62.     _farpokeb(_dos_ds, tbuf_la++, 'A' + drv_no - 1);
  63.     _farpokeb(_dos_ds, tbuf_la++, ':');
  64.     _farpokeb(_dos_ds, tbuf_la++, '\\');
  65.     _farpokeb(_dos_ds, tbuf_la++, '\0');
  66.   }
  67.  
  68.   r.x.ax = 0x71a0;    /* Get Volume Information function */
  69.   r.x.ds = tbuf_seg;    /* DS:DX points to root directory name */
  70.   r.x.dx = 0;
  71.   r.x.es = tbuf_seg;    /* ES:DI points to a buffer for filesys name */
  72.   r.x.di = (tbuf_la - __tb) & 0xffff;
  73.   r.x.cx = 32;        /* max size of filesystem name (Interrupt List) */
  74.   __dpmi_int(0x21, &r);
  75.  
  76.   if ((r.x.flags & 1) == 0 && r.x.ax != 0x7100)
  77.   {
  78.     char *p = fsystype, c;
  79.  
  80.     retval   = r.x.bx;
  81.     if (maxfile)
  82.       *maxfile = r.x.cx;
  83.     if (maxpath)
  84.       *maxpath = r.x.dx;
  85.  
  86.     if (fsystype)
  87.     {
  88.       /* Only copy as much as required, in case the
  89.      buffer isn't large enough for 32 bytes.  */
  90.       _farsetsel (_dos_ds);
  91.       while ((c = _farnspeekb (tbuf_la++)))
  92.     *p++ = c;
  93.       *p = '\0';
  94.     }
  95.   }
  96.   else
  97.   {
  98.     errno = ENOSYS;
  99.     retval = 0;    /* meaning none of the features supported */
  100.     if (maxfile)
  101.       *maxfile = 13;
  102.     if (maxpath)
  103.       *maxpath = 80;
  104.     if (fsystype)
  105.       *fsystype = '\0';
  106.   }
  107.  
  108.   return retval;
  109. }
  110.  
  111. char
  112. _use_lfn (const char *path)
  113. {
  114.   int same_drive_as_last_time;
  115.  
  116.   if (_crt0_startup_flags & _CRT0_FLAG_NO_LFN)
  117.   {
  118.     /* Don't update the static counters, so the first time
  119.        after NO_LFN flag is reset, the environment and the
  120.        filesystem will be queried.  */
  121.     return 0;
  122.   }
  123.  
  124.   same_drive_as_last_time = 1;
  125.   if (path)
  126.   {
  127.     /* FIXME: a UNC PATH will always force a call to `_get_volume_info'.  */
  128.     if ((path[1] == ':' && toupper (*path) != last_drive)
  129.     || (*path == '\\' && path[1] == '\\'))
  130.       same_drive_as_last_time = 0;
  131.     else
  132.     {
  133.       unsigned drv_no;
  134.  
  135.       _dos_getdrive(&drv_no);
  136.       if (drv_no - 1 + 'A' != last_drive)
  137.     same_drive_as_last_time = 0;
  138.     }
  139.   }
  140.  
  141.   if (same_drive_as_last_time
  142.       && last_env_changed  == __environ_changed
  143.       && use_lfn_bss_count == __bss_count
  144.       && filesystem_flags  != _FILESYS_UNKNOWN)    /* paranoia */
  145.     return (filesystem_flags & _FILESYS_LFN_SUPPORTED) != 0;
  146.   else
  147.   {
  148.     char *lfnenv;
  149.  
  150.     use_lfn_bss_count = __bss_count;
  151.     last_env_changed  = __environ_changed;
  152.  
  153.     lfnenv = getenv ("LFN");
  154.     if(lfnenv && (tolower (lfnenv[0]) == 'n'))
  155.     {
  156.       filesystem_flags &= ~_FILESYS_LFN_SUPPORTED;
  157.       last_drive = 0;
  158.       return 0;
  159.     }
  160.   }
  161.  
  162.   if (!same_drive_as_last_time || filesystem_flags == _FILESYS_UNKNOWN)
  163.     filesystem_flags = _get_volume_info (path, 0, 0, 0);
  164.  
  165.   return (filesystem_flags & _FILESYS_LFN_SUPPORTED) != 0;
  166. }
  167.  
  168. #ifdef TEST
  169.  
  170. int main (int argc, char *argv[])
  171. {
  172.   char *path = ".";
  173.   unsigned flags;
  174.   char fsname[32];
  175.   int  maxfile, maxpath;
  176.  
  177.   printf ("_USE_LFN reports %d at startup\n", _USE_LFN);
  178.   if (argc > 1)
  179.     path = argv[1];
  180.   flags = _get_volume_info (path, &maxfile, &maxpath, fsname);
  181.   printf ("Flags: %x, MaxFile: %d, MaxPath: %d, FSName: %s\n",
  182.       flags, maxfile, maxpath, fsname);
  183.   _crt0_startup_flags |= _CRT0_FLAG_NO_LFN;
  184.   printf ("_USE_LFN reports %d when _CRT0_FLAG_NO_LFN is set\n", _USE_LFN);
  185.   _crt0_startup_flags &= ~_CRT0_FLAG_NO_LFN;
  186.   putenv ("LFN=y");
  187.   printf ("_USE_LFN reports %d when LFN is set to Y\n", _USE_LFN);
  188.   putenv ("LFN=n");
  189.   printf ("_USE_LFN reports %d when LFN is set to N\n", _USE_LFN);
  190.   return 0;
  191. }
  192.  
  193. #endif
  194.