home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES1.ZIP / LIB / import.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-06  |  35.2 KB  |  875 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    i m p o r t . c                                                 */
  3. /*                                                                    */
  4. /*    File name mapping routines for UUPC/extended                    */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
  9. /*                                                                    */
  10. /*    Changes Copyright (c) 1990-1993 by Kendra Electronic            */
  11. /*    Wonderworks.                                                    */
  12. /*                                                                    */
  13. /*    All rights reserved except those explicitly granted by the      */
  14. /*    UUPC/extended license agreement.                                */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Id: import.c 1.12 1993/11/06 17:54:55 rhg Exp $
  19.  *
  20.  *    $Log: import.c $
  21.  *     Revision 1.12  1993/11/06  17:54:55  rhg
  22.  *     Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  23.  *
  24.  *     Revision 1.11  1993/10/12  00:48:44  ahd
  25.  *     Normalize comments
  26.  *
  27.  *     Revision 1.10  1993/10/09  15:46:15  rhg
  28.  *     ANSIify the source
  29.  *
  30.  *     Revision 1.9  1993/09/27  04:04:06  ahd
  31.  *     Correct creation of pointer to file system name
  32.  *
  33.  *     Revision 1.8  1993/09/26  03:32:27  dmwatt
  34.  *     Use Standard Windows NT error message module
  35.  *
  36.  *     Revision 1.7  1993/09/20  04:38:11  ahd
  37.  *     TCP/IP support from Dave Watt
  38.  *     't' protocol support
  39.  *     OS/2 2.x support
  40.  *
  41.  *     Revision 1.6  1993/09/03  12:54:55  ahd
  42.  *     Add missing endif
  43.  *
  44.  *     Revision 1.5  1993/09/03  12:18:55  dmwatt
  45.  *     Windows NT support for long names on file systems
  46.  *
  47.  *     Revision 1.4  1993/09/02  12:08:17  ahd
  48.  *     HPFS Support
  49.  *
  50.  *     Revision 1.3  1993/04/11  00:31:31  dmwatt
  51.  *     Global edits for year, TEXT, etc.
  52.  *
  53.  * Revision 1.2  1992/11/22  21:06:14  ahd
  54.  * Correct mapping of dos paths with trailing slashes
  55.  *
  56.  */
  57.  
  58. /*--------------------------------------------------------------------*/
  59. /*                        System include files                        */
  60. /*--------------------------------------------------------------------*/
  61.  
  62. #include <stdio.h>
  63. #include <ctype.h>
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include <time.h>
  67.  
  68. #if defined(FAMILYAPI) || defined(__OS2__)
  69. #define INCL_NOPM             /* No need to include OS/2 PM info */
  70. #define INCL_BASE
  71. #include <os2.h>
  72. #elif defined(WIN32)
  73. #include <windows.h>
  74. #endif
  75.  
  76. /*--------------------------------------------------------------------*/
  77. /*                    UUPC/extended include files                     */
  78. /*--------------------------------------------------------------------*/
  79.  
  80. #include "lib.h"
  81. #include "import.h"
  82. #include "arbmath.h"
  83. #include "hostable.h"
  84. #include "usertabl.h"
  85. #include "security.h"
  86.  
  87. #ifdef WIN32
  88. #include "pnterr.h"
  89. #endif
  90.  
  91. #define MAX_DIGITS 20         /* Number of digits for arb math */
  92.  
  93. /*--------------------------------------------------------------------*/
  94. /*                    Internal function prototypes                    */
  95. /*--------------------------------------------------------------------*/
  96.  
  97. #define min(x,y) (((x) < (y)) ? (x) : (y))
  98.  
  99. currentfile();
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*                     Local function prototypes                      */
  103. /*--------------------------------------------------------------------*/
  104.  
  105. static void ImportName( char *local,
  106.                         const char *canon,
  107.                         size_t charsetsize,
  108.                         const boolean longname );
  109.  
  110. static boolean advancedFS( const char *path );
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*                                                                    */
  114. /*   i m p o r t p a t h                                              */
  115. /*                                                                    */
  116. /*   Convert a canonical name to a format the host can handle         */
  117. /*                                                                    */
  118. /*   These routines convert file name between canonical form, which   */
  119. /*   is defined as a 'unix' style pathname, and the MS-DOS all        */
  120. /*   uppercase "xxxxxxxx.xxx" format.                                 */
  121. /*                                                                    */
  122. /*   If the canonical name does not have a path, that is the file is  */
  123. /*   destined for the local spool directory, we can assume the UNIX   */
  124. /*   name will normally be in a format like this:                     */
  125. /*                                                                    */
  126. /*                                                                    */
  127. /*       X.hostid#######            (Execute files)                   */
  128. /*       C.hostid#######            (Call files)                      */
  129. /*       D.hostid#######            (Data files)                      */
  130. /*                                                                    */
  131. /*   where "hostid" may be most, but not always all, of the local     */
  132. /*   host or remote host (the file came from or is going to) and      */
  133. /*   "######" can be any character valid for the UNIX file system.    */
  134. /*   Note, however, that the routine has to be generic to allow for   */
  135. /*   other file names to be placed in the spool directory without     */
  136. /*   collisions.                                                      */
  137. /*                                                                    */
  138. /*   Avoiding collisions in the spool directory is important; when    */
  139. /*   receiving files with mixed case names longer than 11             */
  140. /*   characters, sooner or later a file name collision will occur.    */
  141. /*                                                                    */
  142. /*   We can also assume that only UUPC will see these names, which    */
  143. /*   means we can transform the name using any method we choose, so   */
  144. /*   long as the UUPC functions opening the file always call          */
  145. /*   importpath, and that importpath is reducible (that is, two       */
  146. /*   calls to importpath with the same argument always yield the      */
  147. /*   same result).  Note that if end user really wanted the file in   */
  148. /*   the spool directory, all he has to do is rename the file-- far   */
  149. /*   better than losing the data because duplicate file names.        */
  150. /*                                                                    */
  151. /*   For these files, we map the name as follows:                     */
  152. /*                                                                    */
  153. /*   0 - If the name is a valid MS-DOS name, use it without changing  */
  154. /*                                                                    */
  155. /*   1 - Begin the output name by inserting up to the first eight     */
  156. /*       characters of the remote host name (followed by a slash) as  */
  157. /*       a subdirectory name.                                         */
  158. /*                                                                    */
  159. /*   2 - If the input name begins with an uppercase alphabetic        */
  160. /*       character followed by a period, also insert the alphabetic   */
  161. /*       (followed by a slash) to make this a second subdirectory.    */
  162. /*       Then, move the logical start of the input name past the two  */
  163. /*       characters.                                                  */
  164. /*                                                                    */
  165. /*   3 - Determine the number of characters the local host and        */
  166. /*       remote hosts have equal to the next characters of the input  */
  167. /*       name, up to a maximum of 8, and zero the lower of the two    */
  168. /*       counts.  Then, step past the number of characters of the     */
  169. /*       larger count.                                                */
  170. /*                                                                    */
  171. /*       For example, if the file name is X.keane22222 and the local  */
  172. /*       host name is kendra (2 characters match) and the remote      */
  173. /*       host is keane1 (5 characters match), zero the number of      */
  174. /*       characters matched by kendra, and make the new start of the  */
  175. /*       file name five characters further (at the first "2").        */
  176. /*                                                                    */
  177. /*   4 - Convert the remaining string using a base conversion, with   */
  178. /*       the input character size being from ascii "#" to ascii "z"   */
  179. /*       (88 characters) to the allowed set of characters in MS-DOS   */
  180. /*       file names (charset, below, 52 characters).                  */
  181. /*                                                                    */
  182. /*   5 - Prepend to the string to be converted the length of the      */
  183. /*       remote host added to the length of the local host            */
  184. /*       multiplied by 8 (both lengths were computed in step 3,       */
  185. /*       above).  The base conversion is also applied to this         */
  186. /*       "character", we which know will be in the range 1-64.        */
  187. /*                                                                    */
  188. /*   6 - If the string created by steps 4 and 5 exceeds 8             */
  189. /*       characters, insert a period after the eighth character to    */
  190. /*       make it a valid MS-DOS file name.  If the string created by  */
  191. /*       steps 4 and 5 exceeds 11 characters, truncate the string by  */
  192. /*       using the first eight and last three characters.             */
  193. /*                                                                    */
  194. /*   7 - Append the string created in steps 4 through 6 to the path   */
  195. /*       name created in steps 1 and 2.                               */
  196. /*                                                                    */
  197. /*   If the canonical name has a path, it is destined for an end      */
  198. /*   user, so we should not radically transform it like we do for     */
  199. /*   files in the spool directory.  Thus, if the canonical name has   */
  200. /*   a path, mung the canonical file name as follows:                 */
  201. /*                                                                    */
  202. /*   1 - skip any path from the canonical name                        */
  203. /*                                                                    */
  204. /*   2 - copy up to 8 character from the canonical name converting .  */
  205. /*       to _ and uppercase to lowercase.                             */
  206. /*                                                                    */
  207. /*   3 - if the name was longer than 8 character copy a . to the      */
  208. /*       host name and then copy the up to three characters from      */
  209. /*       the tail of the canonical name to the host name.             */
  210. /*                                                                    */
  211. /*   Note that this set of rules will cause a collision with names    */
  212. /*   that only differ in case, but leaves the name in a recongizable  */
  213. /*   format for the user.                                             */
  214. /*--------------------------------------------------------------------*/
  215.  
  216. void importpath(char *local, const char *canon, const char *remote)
  217. {
  218.    char *s, *out;
  219.    size_t charsetsize;     /* Number of allowed characters in
  220.                               MS-DOS file names                   */
  221.  
  222.    out = local;
  223.  
  224. /*--------------------------------------------------------------------*/
  225. /*                       Verify our parameters                        */
  226. /*--------------------------------------------------------------------*/
  227.  
  228.    if ( local == NULL )
  229.       panic();
  230.  
  231.    if ( canon == NULL )
  232.       panic();
  233.  
  234. /*--------------------------------------------------------------------*/
  235. /*                      Define our character set                      */
  236. /*--------------------------------------------------------------------*/
  237.  
  238.     if ( E_charset == NULL )
  239.        E_charset = DOSCHARS;
  240.  
  241.     charsetsize = strlen( E_charset );
  242.  
  243. /*--------------------------------------------------------------------*/
  244. /*                 Determine if spool file directory                  */
  245. /*--------------------------------------------------------------------*/
  246.  
  247.    if ((s = strrchr(canon, '/')) == NULL)
  248.    {                          /* File for spooling directory, use
  249.                                  internal character set to avoid
  250.                                  collisions                           */
  251.       static size_t range =  UNIX_END_C - UNIX_START_C + 1;
  252.                               /* Determine unique number characters in
  253.                                  the UNIX file names we are mapping   */
  254.  
  255.       size_t remlen = min(HOSTLEN, strlen(remote));
  256.                               /* Length of the remote name passed
  257.                                  in, shortened below to number of
  258.                                  characters matched in name           */
  259.       size_t nodelen = min(HOSTLEN, strlen(E_nodename));
  260.                               /* Length of the local host name,
  261.                                  shortened below to number of
  262.                                  characters matched in name           */
  263.       size_t subscript = 0;   /* Value of UNIX character to be
  264.                                  converted to MS-DOS character set    */
  265.       char *next        = local + remlen;
  266.       char tempname[FILENAME_MAX];
  267.       unsigned char number[MAX_DIGITS];
  268.                               /* Arbitary length number, for base
  269.                                  conversions                        */
  270.  
  271.       boolean longname;
  272.  
  273.       printmsg(4,"importpath: Checking File system for spool directory %s",
  274.                   E_spooldir );
  275.       longname = advancedFS( E_spooldir ) && bflag[B_LONGNAME];
  276.  
  277. /*--------------------------------------------------------------------*/
  278. /*                    Verify we have a remote name                    */
  279. /*--------------------------------------------------------------------*/
  280.  
  281.       if ( remote == NULL )
  282.          panic();
  283.  
  284. /*--------------------------------------------------------------------*/
  285. /*    Put the host name (up to six characters) at the beginning of    */
  286. /*    the MS-DOS file name as a sub-directory name.                   */
  287. /*--------------------------------------------------------------------*/
  288.  
  289.       strncpy(local, remote, remlen);
  290.       *next++ = '/';          /* Add in the sub-directory seperator   */
  291.       s = (char *) canon;     /* Get the beginnging of the UNIX name  */
  292.  
  293. /*--------------------------------------------------------------------*/
  294. /*    Files in the spooling directory generally start with "D.",      */
  295. /*    "C.", or "X."; strip off any upper case letter followed by a    */
  296. /*    period into its own directory.                                  */
  297. /*--------------------------------------------------------------------*/
  298.  
  299.       if ((s[0] >= 'A') && (s[0] <= 'Z') && (s[1] == '.'))
  300.       {
  301.          *next++ = *s;        /* Copy the input character             */
  302.          *next++ = '/';       /* Add the sub-directory indicator too  */
  303.          s += 2;              /* Step input string past the copied
  304.                                  data                                 */
  305.       }
  306.  
  307.       while( remlen > 0 )
  308.       {
  309.          if (equaln(remote,s,remlen))
  310.             break;
  311.          remlen--;
  312.       }
  313.  
  314.       while( nodelen > 0 )
  315.       {
  316.          if (equaln(E_nodename,s,nodelen))
  317.             break;
  318.          nodelen--;
  319.       }
  320.  
  321.       if (nodelen > remlen )
  322.       {
  323.          remlen = 0;
  324.          s += nodelen;
  325.       }
  326.       else {
  327.          nodelen = 0;
  328.          s += remlen;
  329.       }
  330.  
  331.       *next  = '\0';          /* Terminate first part of host string  */
  332.  
  333. /*--------------------------------------------------------------------*/
  334. /*       Create a binary number which represents our file name        */
  335. /*--------------------------------------------------------------------*/
  336.  
  337.       for (subscript = 0; subscript < MAX_DIGITS; subscript++ )
  338.          number[subscript] = 0;  /* Initialize number to zero         */
  339.  
  340.       add(number, nodelen + remlen * HOSTLEN, MAX_DIGITS);
  341.                                  /* Append host name info to the
  342.                                     front of the converted string     */
  343.  
  344.       while( (*s != '\0') && (*number == '\0'))
  345.       {
  346.          mult(number, range, MAX_DIGITS); /* Shift the number over    */
  347.          add(number, *s++  - UNIX_START_C , MAX_DIGITS);
  348.                                           /* Add in new low order     */
  349.       } /* while */
  350.  
  351. /*--------------------------------------------------------------------*/
  352. /*   We now have stripped off the leading x. and host name, if any;   */
  353. /*   now, convert the remaining characters in the name by doing a     */
  354. /*   range to charset base conversion.                                */
  355. /*--------------------------------------------------------------------*/
  356.  
  357.       out = &tempname[FILENAME_MAX];
  358.       *--out = '\0';          /* Terminate the string we will build   */
  359.  
  360. /*--------------------------------------------------------------------*/
  361. /*         Here's the loop to actually do the base conversion         */
  362. /*--------------------------------------------------------------------*/
  363.  
  364.       while(adiv( number, charsetsize, &subscript, MAX_DIGITS))
  365.             *--out = E_charset[ subscript ];
  366.  
  367. /*--------------------------------------------------------------------*/
  368. /*    The conversion is done; now squeeze it into an 11 character     */
  369. /*    MS-DOS name with period.                                        */
  370. /*--------------------------------------------------------------------*/
  371.  
  372.       ImportName( next, out, charsetsize, longname );
  373.  
  374.    }
  375.    else {         /* Not file for spooling directory, convert it  */
  376.  
  377.       char *in = (char *) canon;
  378.       boolean longname ;
  379.  
  380.       printmsg(4,"importpath: Checking file system for file %s",
  381.                   canon );
  382.       longname = advancedFS( canon );
  383.  
  384.       if ( ValidDOSName( canon, longname ))
  385.       {
  386.          strcpy( local, canon );
  387.          return;
  388.       }
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*      Handle leading drive letter (ignore it, assuming valid)       */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.       if ( isalpha( *in ) && (in[1] == ':'))
  395.       {
  396.          *out++ = *in++;      /* The drive letter                     */
  397.          *out++ = *in++;      /* The colon making it a driver letter  */
  398.       } /* if */
  399.  
  400.       if ( *in == '/' )       /* Absolute path name?                  */
  401.          *out++ = *in++;      /* Yes, step past it                    */
  402.  
  403.       while( *in == '/')      /* Additional slashes?                  */
  404.          in++;                /* Skip them,  they mean nothing        */
  405.  
  406.       s = strchr( in, '/' );  /* Get end of next path segment         */
  407.  
  408. /*--------------------------------------------------------------------*/
  409. /*              Now convert each simple name in the path              */
  410. /*--------------------------------------------------------------------*/
  411.  
  412.       while ( *in )
  413.       {
  414.          if ( s != NULL )
  415.             *s = '\0';        /* Truncate input string to simple name */
  416.  
  417.          ImportName( out, in , charsetsize, longname );
  418.  
  419.          if ( s == NULL )
  420.             break;
  421.          out = out + strlen( out );
  422.          *out++ = *s++ = '/'; /* Restore path to input and output     */
  423.          in = s;              /* Remember start of this simple name   */
  424.          while( *in == '/')   /* Additional slashes?                  */
  425.             in++;             /* Skip them,  they mean nothing        */
  426.          s = strchr( in , '/' );
  427.       }
  428.  
  429.    } /* else */
  430.  
  431.    printmsg( 3, "ImportPath: Mapped %s to %s", canon, local );
  432.  
  433. } /*importpath*/
  434.  
  435. /*--------------------------------------------------------------------*/
  436. /*    I m p o r t N a m e                                             */
  437. /*                                                                    */
  438. /*    Translate a simple DOS name without the path                    */
  439. /*--------------------------------------------------------------------*/
  440.  
  441. static void ImportName( char *local,
  442.                         const char *canon,
  443.                         size_t charsetsize,
  444.                         const boolean longname )
  445. {
  446.  
  447.    char *in = (char *) canon;
  448.    char *out = local;
  449.    size_t len = strlen( canon );
  450.    size_t column;
  451.    char *best_period = NULL;     /* Assume no prince charming         */
  452.  
  453.    if ( strchr(canon,'/') != NULL )
  454.    {
  455.       printmsg(0,"ImportName: Parameter error, not simple name: %s",
  456.             canon);
  457.       panic();
  458.    }
  459.  
  460.    if ( len == 0 )
  461.    {
  462.       printmsg(0,"ImportName: Parameter error, zero length input");
  463.       panic();
  464.    }
  465.  
  466. /*--------------------------------------------------------------------*/
  467. /*                 If a valid DOS name, use it as-is                  */
  468. /*--------------------------------------------------------------------*/
  469.  
  470.    if (ValidDOSName( canon, longname ))
  471.    {
  472.       strcpy( local, canon );
  473.       return;
  474.    }
  475.  
  476. /*--------------------------------------------------------------------*/
  477. /*    If the dataset name has a period, use it.  The rule we          */
  478. /*    follow is use the last period in the second through ninth       */
  479. /*    characters, otherwise use the last period in the dataset        */
  480. /*    name with the exception of leading period.                      */
  481. /*                                                                    */
  482. /*    In any case, we only copy up to eight characters for the        */
  483. /*    dataset name and up to three characters for the extension.      */
  484. /*--------------------------------------------------------------------*/
  485.  
  486.    for ( column = 1; (column < 9) && (in[column] != '\0') ; column++)
  487.    {
  488.       if ( in[column] == '.')
  489.       {
  490.          strncpy( out, in, column + 5 );
  491.                                     /* Period, 3 char extension,
  492.                                        and terminating \0             */
  493.          best_period = &out[column];/* Remember output location of
  494.                                        period in name                 */
  495.  
  496.          if ( len > (column + 4) )  /* Need to trunc extension to 3?  */
  497.             strcpy( out + column + 1, in + len - 3 ); /* Yes          */
  498.  
  499.          break;
  500.       } /*if */
  501.    }  /* if */
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*    No period in the first eight characters, search the rest of     */
  505. /*    the name for the last period (unless period is very last        */
  506. /*    character in the string).                                       */
  507. /*--------------------------------------------------------------------*/
  508.  
  509.    if ( best_period == NULL )
  510.    {
  511.  
  512.       strncpy( out , in , 8);
  513.       best_period = strrchr( in+1 , '.');
  514.  
  515.       if ( (best_period != NULL) && (best_period[1] != '\0') )
  516.       {
  517.          strncpy( &out[8], best_period, 4 ); /* Plus period and 3
  518.                                                 in extension          */
  519.  
  520.          if ( strlen( best_period) > 4 )     /* Long Extension?       */
  521.             out[12] = '\0';                  /* Yes --> Truncate      */
  522.  
  523.       } /* if */
  524.       else {                  /* No periods at all, generate one
  525.                                  if needed for long name          */
  526.  
  527.          if ( len > 8 )
  528.          {
  529.             out[8] = '.';
  530.             strcpy(&out[9], in + max(8,(len - 3))  );
  531.          } /* if ( len > 9 ) */
  532.  
  533.       } /* else */
  534.  
  535.       best_period = &out[8];              /* Remember location of
  536.                                              period, okay if past
  537.                                              end of string            */
  538.  
  539.    } /* if ( best_period == NULL ) */
  540.  
  541. /*--------------------------------------------------------------------*/
  542. /*                Now, clean up any invalid characters                */
  543. /*--------------------------------------------------------------------*/
  544.  
  545.    if ( out[ strlen( out ) - 1 ] == '.' ) /* Trailing period?         */
  546.       out[ strlen( out ) - 1 ] = '\0';    /* Just truncate string     */
  547.  
  548.    while( *out != '\0')
  549.    {
  550.       int c ;
  551.       if ( isupper( *out ))
  552.          c = tolower( *out );
  553.       else
  554.          c = *out;
  555.  
  556.       if ((out != best_period) && (strchr( E_charset, c ) == NULL ))
  557.       {
  558.          if ( c > 'z' )
  559.             c -= 62;
  560.          else if ( c > 'Z' )
  561.             c -= 36;
  562.          else if ( c > '9' )
  563.             c -= 10;
  564.          *out = E_charset[ (c - UNIX_START_C) % charsetsize ];
  565.       }
  566.  
  567.       out++;                    /* Step to next character         */
  568.    } /* while( *out != '\0') */
  569.  
  570. /*--------------------------------------------------------------------*/
  571. /*                   Report our results and return                    */
  572. /*--------------------------------------------------------------------*/
  573.  
  574.    printmsg( 5,
  575.             "ImportName: Mapped %s to %s", canon, local );
  576.  
  577. } /* ImportName */
  578.  
  579. /*--------------------------------------------------------------------*/
  580. /*    V a l i d D O S N a m e                                         */
  581. /*                                                                    */
  582. /*    Validate an MS-DOS file name                                    */
  583. /*--------------------------------------------------------------------*/
  584.  
  585. boolean ValidDOSName( const char *s,
  586.                       const boolean longname )
  587. {
  588.    char *ptr;
  589.    size_t len = strlen ( s );
  590.    char tempname[FILENAME_MAX];
  591.  
  592.    static char *longCharSet = NULL;
  593.  
  594. /*--------------------------------------------------------------------*/
  595. /*                      Define our character set                      */
  596. /*--------------------------------------------------------------------*/
  597.  
  598.    if ( E_charset == NULL )
  599.       E_charset = DOSCHARS;
  600.  
  601.    if ( longname )
  602.    {
  603.  
  604. #if defined(FAMILYAPI) || defined(__OS2__)
  605.  
  606. /*--------------------------------------------------------------------*/
  607. /*       Ask OS/2 if the file name is okay.  Because the invoked      */
  608. /*       function accepts wildcards, we pre-test for them and reject  */
  609. /*       them as needed.                                              */
  610. /*--------------------------------------------------------------------*/
  611.  
  612.       if ((strchr( s, '*') == NULL ) && (strchr( s, '?') == NULL))
  613.       {
  614.  
  615. #ifdef __OS2__
  616.          APIRET result = DosQPathInfo( (PSZ) s,
  617.                                        FIL_QUERYFULLNAME,
  618.                                        (PVOID) tempname,
  619.                                        sizeof tempname );
  620. #else
  621.          USHORT result = DosQPathInfo( (PSZ) s,
  622.                                        FIL_NAMEISVALID,
  623.                                        (PBYTE) tempname,
  624.                                        sizeof tempname,
  625.                                        0 );
  626.  
  627. #endif
  628.          if ( result == 0 )
  629.             return TRUE;
  630.  
  631.          printmsg(2,
  632.                   "ValidDOSName: Invalid name %s, syntax error code %d",
  633.                    s,
  634.                    (int) result);
  635.  
  636.       } /* if */
  637.  
  638. #endif
  639.  
  640.       if ( longCharSet == NULL )
  641.       {
  642.          *tempname = '.';
  643.          longCharSet = newstr(strcpy( tempname + 1, E_charset ));
  644.       }
  645.  
  646.       if (strspn(s, longCharSet) == len)
  647.       {
  648.          printmsg(9,"ValidDOSName: \"%s\" is valid long name", s);
  649.          return TRUE;
  650.       }
  651.  
  652.    } /* if ( longname ) */
  653.  
  654. /*--------------------------------------------------------------------*/
  655. /*                 Name must be 12 characters or less                 */
  656. /*--------------------------------------------------------------------*/
  657.  
  658.    if (len > 12)
  659.       return FALSE;
  660.  
  661.    strcpy( tempname, s);      /* Make a temp copy we can alter        */
  662.  
  663. /*--------------------------------------------------------------------*/
  664. /*    Simple file name without extension must be eight characters     */
  665. /*    or less                                                         */
  666. /*--------------------------------------------------------------------*/
  667.  
  668.    ptr = strrchr(tempname, '.');
  669.    if (ptr == NULL)
  670.    {
  671.       if (len > 8)
  672.          return FALSE;
  673.    }
  674.  
  675. /*--------------------------------------------------------------------*/
  676. /*          Period must be in second through ninth character          */
  677. /*--------------------------------------------------------------------*/
  678.  
  679.    else {
  680.       if ((ptr == tempname) || (ptr > &tempname[8]))
  681.          return FALSE;
  682.  
  683. /*--------------------------------------------------------------------*/
  684. /*             Extension must be three characters or less             */
  685. /*--------------------------------------------------------------------*/
  686.  
  687.       if ( strlen( ptr ) > 4) /* Three characters plus the period?    */
  688.          return FALSE;        /* No --> Too much                      */
  689.  
  690. /*--------------------------------------------------------------------*/
  691. /*                          Only one period                           */
  692. /*--------------------------------------------------------------------*/
  693.  
  694.       if (ptr != strchr(tempname, '.'))
  695.          return FALSE;
  696.    } /* else */
  697.  
  698. /*--------------------------------------------------------------------*/
  699. /*                Must only be valid MS-DOS characters                */
  700. /*--------------------------------------------------------------------*/
  701.  
  702.    strlwr( tempname );        /* Map into our desired character set   */
  703.    if ( ptr != NULL )
  704.       *ptr = 'x';             /* We've already accounted for the
  705.                                  period, don't let it ruin our day    */
  706.  
  707.    if (strspn(tempname, E_charset ) == len)
  708.    {
  709.       printmsg(9,"ValidDOSName: \"%s\" is valid", s);
  710.       return TRUE;
  711.    }
  712.    else
  713.       return FALSE;
  714.  
  715. } /* ValidateDOSName */
  716.  
  717. #if defined(FAMILYAPI) || defined( __OS2__ )
  718.  
  719. /*--------------------------------------------------------------------*/
  720. /*       a d v a n c e d F S                       (OS/2 version)     */
  721. /*                                                                    */
  722. /*       Determine if a file system is advanced (supports better than */
  723. /*       8.3 file names)                                              */
  724. /*--------------------------------------------------------------------*/
  725.  
  726. static boolean advancedFS( const char *path )
  727. {
  728.    char buf[BUFSIZ];             /* One generic large buffer          */
  729.  
  730. #ifdef __OS2__
  731.    ULONG bufSize = sizeof buf;
  732.    FSQBUFFER2 *dataBuffer = (FSQBUFFER2 *) buf;
  733.    ULONG  result;
  734. #else
  735.    SHORT bufSize = sizeof buf;
  736.    FSQBUFFER *dataBuffer = (FSQBUFFER *) buf;
  737.    USHORT result;
  738. #endif
  739.  
  740. /*--------------------------------------------------------------------*/
  741. /*                  Get the drive letter to process                   */
  742. /*--------------------------------------------------------------------*/
  743.  
  744.    char driveInfo[3];
  745.    char *fileSystem;
  746.  
  747.    if ( isalpha( *path ) && (path[1] == ':') )
  748.       strncpy( driveInfo, path, 2 );
  749.    else
  750.       strncpy( driveInfo, E_cwd, 2 );
  751.  
  752.    driveInfo[ sizeof(driveInfo) - 1 ] = '\0';   /* Terminate string data */
  753.  
  754. /*--------------------------------------------------------------------*/
  755. /*      Query the drive (both 1.x and 2.x calls are supported).       */
  756. /*--------------------------------------------------------------------*/
  757.  
  758. #ifdef __OS2__
  759.    result = DosQueryFSAttach( (PSZ) driveInfo,
  760.                           1,
  761.                           FSAIL_QUERYNAME,
  762.                           dataBuffer,
  763.                           &bufSize );
  764.    fileSystem = (char *) (dataBuffer->szFSDName + dataBuffer->cbName);
  765. #else
  766.    result = DosQFSAttach( driveInfo,
  767.                           0,
  768.                           FSAIL_QUERYNAME,
  769.                           (PBYTE) buf,
  770.                           &bufSize,
  771.                           0L );
  772.    fileSystem = (char *) (dataBuffer->szFSDName + dataBuffer->cbName - 1);
  773. #endif
  774.  
  775.    if ( result != 0 )
  776.    {
  777.       printmsg(0, "advancedFS: Unable to query file system for %s, error = %d",
  778.                   driveInfo,
  779.                   (int)  result );
  780.       return FALSE;
  781.    }
  782.  
  783.  
  784.    printmsg(4,"advancedFS: File system %d, name \"%s\", FS name \"%s\"",
  785.                (int) dataBuffer->iType,
  786.                dataBuffer->szName,
  787.                fileSystem );
  788.  
  789.    if (equal( fileSystem, "FAT"))
  790.       return FALSE;
  791.    else
  792.       return TRUE;
  793.  
  794. } /* advancedFS */
  795.  
  796. #elif WIN32
  797.  
  798. /*--------------------------------------------------------------------*/
  799. /*       a d v a n c e d F S                    (Window NT version)   */
  800. /*                                                                    */
  801. /*       Determine if a file system is advanced (supports better than */
  802. /*       8.3 file names)                                              */
  803. /*--------------------------------------------------------------------*/
  804.  
  805. static boolean advancedFS( const char *path )
  806. {
  807.    char driveInfo[4];
  808.    char fsType[5];
  809.    BOOL result;
  810.    char *shareNameEnd;
  811.  
  812.    if ( !path || *path == '\0' ) {       /* use CWD                   */
  813.       strncpy( driveInfo, E_cwd, 3);
  814.       driveInfo[3] = '\0';
  815.    }
  816.    else if ( isalpha( *path ) && (path[1] == ':') )
  817.    {                                   /* It's a local drive          */
  818.  
  819.       printmsg(5, "advancedFS: it's a drive letter");
  820.       strncpy( driveInfo, path, 3 );
  821.       driveInfo[3] = '\0';          /* Terminate drive string data    */
  822.  
  823.    }
  824.    else
  825.       return FALSE;
  826.  
  827. /*--------------------------------------------------------------------*/
  828. /*            We've got the drive letter, query its status            */
  829. /*--------------------------------------------------------------------*/
  830.  
  831.    result = GetVolumeInformation(driveInfo, NULL, 0, NULL, NULL,
  832.          NULL, fsType, 5);
  833.  
  834.    if ( !result )
  835.    {
  836.       DWORD dwError = GetLastError();
  837.       printmsg(0, "advancedFS: Unable to query file system for %s", driveInfo);
  838.       printNTerror("GetVolumeInformation", dwError);
  839.       panic();
  840.    }
  841.  
  842.    printmsg(4,"advancedFS: File system for \"%s\" has name \"%s\"",
  843.                driveInfo,
  844.                fsType );
  845.  
  846.    return strcmp( fsType, "FAT");
  847.  
  848. } /* advancedFS for WIN32 */
  849.  
  850. #else
  851.  
  852. /*--------------------------------------------------------------------*/
  853. /*       a d v a n c e d F S                          (DOS version)   */
  854. /*                                                                    */
  855. /*       Determine if a file system is advanced (supports better than */
  856. /*       8.3 file names)                                              */
  857. /*--------------------------------------------------------------------*/
  858.  
  859. #ifdef __TURBOC__
  860. #pragma argsused
  861. #elif _MSC_VER >= 700
  862. #pragma warning(disable:4100)   /* suppress unref'ed formal param. warnings */
  863. #endif
  864.  
  865. static boolean advancedFS( const char *path )
  866. {
  867.    return FALSE;                 /* DOS is always dumb on file systems! */
  868. } /* advancedFS for MS-DOS */
  869.  
  870. #if _MSC_VER >= 700
  871. #pragma warning(default:4100)   /* restore unref'ed formal param. warnings */
  872. #endif
  873.  
  874. #endif
  875.