home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / fdir / fdir.c next >
Encoding:
C/C++ Source or Header  |  1990-07-05  |  12.7 KB  |  401 lines

  1. /*************************************************************
  2.  
  3.  This sample code demonstrates conversion from longnames to 8.3 and how
  4.  to determine the longname from the EA of a FAT file.
  5.  Should be compiled with the Large model.
  6.  
  7.  Written by Jeff Johnson 6/20/89
  8.  
  9.  This code was written to demonstrate two new features of OS/2 V1.2:
  10.  1) How to convert long filenames to the appropriate 8.3 names.
  11.  2) How to find a file's longname on a FAT system by checking its EA.
  12.  
  13.  Procedures in this file:
  14.    main()             Does the main directory program calling support modules
  15.    Convert_to_8dot3() Converts a longname to 8.3 name
  16.    ParsePathName()    Breaks a full path into its 3 components
  17.    QueryLongname()    Gets the .LONGNAME EA for a given file
  18.    QueryIFS()         Determines the IFS type of a drive
  19.  
  20. **************************************************************/
  21.  
  22. #define INCL_DOSFILEMGR
  23. #define INCL_BASE
  24. #include <os2.h>
  25.  
  26. #include <string.h>
  27. #include <malloc.h>
  28. #include <stdio.h>
  29.  
  30. #define FAT  0
  31. #define HPFS 1
  32. #define GetInfoLevel1 0x0001
  33. #define GetInfoLevel3 0x0003
  34.  
  35. VOID Convert_to_8dot3(CHAR *,CHAR *);
  36. VOID ParsePathName(CHAR *,CHAR *,CHAR *,CHAR *);
  37. VOID QueryLongname(CHAR *,CHAR *);
  38. VOID QueryIFS(CHAR *,PUSHORT,PUSHORT);
  39.  
  40.  
  41. /*
  42.  * Function name: main()
  43.  *
  44.  * Parameters:  argc, argv.  If the user places a file spec on the command
  45.  *              line it is used to select/filter the directory listing.
  46.  *              Otherwise, the default directory is listed.
  47.  *
  48.  * Returns: Always exits with 0.
  49.  *
  50.  * Purpose: main() coordinates the directory process by calling the
  51.  *          appropriate setup routines, then handling the DosFindNext
  52.  *          loop for each file.
  53.  *
  54.  * Usage/Warnings:  Very little error checking is done as the code is written
  55.  *                  to demonstrate longname conversion/EA reading, not as
  56.  *                  a finished app.
  57.  *
  58.  * Calls: ParsePathName(), QueryIFS(), Convert_to_8dot3(), QueryLongname()
  59.  */
  60.  
  61. main (int argc, char *argv[])
  62. {
  63.     USHORT uRetval,hdir=0xffff,SearchCount=1;
  64.     PFILEFINDBUF pfbuf;
  65.     char szDrive[3],szPath[260],szFilename[CCHMAXPATH],szFullPath[CCHMAXPATH];
  66.     USHORT ifsloc,ifsname;
  67.     char *szFilePtr,szLongName[260];
  68.  
  69.     if(argc<2)
  70.         ParsePathName("",szDrive,szPath,szFilename);
  71.     else
  72.         ParsePathName(argv[1],szDrive,szPath,szFilename);
  73.  
  74.     if(strlen(szFilename) == 0)
  75.         strcpy(szFilename,"*");
  76.  
  77.     strcpy(szFullPath,szDrive);
  78.     strcat(szFullPath,szPath);
  79.     szFilePtr = szFullPath + strlen(szFullPath);
  80.     strcat(szFullPath,szFilename);
  81.  
  82.     QueryIFS(szDrive,&ifsloc,&ifsname);
  83.  
  84.     if(ifsname != FAT && ifsname != HPFS)
  85.     {
  86.         printf("Unrecognized file system.\n");
  87.         return 0;
  88.     }
  89.  
  90.     if(ifsname == FAT)
  91.         printf("FAT -> HPFS directory listing\n");
  92.     else
  93.         printf("HPFS -> FAT directory listing\n");
  94.  
  95.  
  96.     pfbuf = (PFILEFINDBUF) malloc(sizeof(FILEFINDBUF));
  97.     uRetval=DosFindFirst(szFullPath,(PHDIR) &hdir,FILE_DIRECTORY,
  98.                          pfbuf,sizeof(FILEFINDBUF),&SearchCount,0L);
  99.  
  100.     if(uRetval)
  101.     {
  102.         printf("No files found.\n");
  103.         return 0;
  104.     }
  105.  
  106.     do
  107.     {
  108.         if(ifsname == FAT)
  109.         {
  110.             strcpy(szFilePtr,pfbuf->achName);  /* Drop in name after path */
  111.  
  112.             QueryLongname(szFullPath,szLongName);
  113.  
  114.             if(strlen(szLongName) == 0)
  115.                 printf("%s\n",pfbuf->achName);
  116.             else
  117.                 printf("%s\n",szLongName);
  118.         }
  119.         else   /* It's HPFS */
  120.         {
  121.             Convert_to_8dot3(pfbuf->achName,szFilename);
  122.             printf("%s\n",szFilename);
  123.         }
  124.     } while(!(uRetval=DosFindNext(hdir,pfbuf,
  125.                                   sizeof(FILEFINDBUF),&SearchCount)));
  126. }
  127.  
  128.  
  129. /*
  130.  * Function name: Convert_to_8dot3()
  131.  *
  132.  * Parameters:  szLong points to the input long file name.
  133.  *              szFat points to a return buffer for the FAT compatible name.
  134.  *
  135.  * Returns: VOID. The converted string is placed in szFat buffer.
  136.  *
  137.  * Purpose: Converts a HPFS longname to the standard 8.3 name.  This is
  138.  *          done as follows:  The extension is the first 3 characters after
  139.  *          the last dot, no extension if there are no dots.  The file stem
  140.  *          is at most 8 character and is taken from the beginning of the
  141.  *          longname string, replacing all dots with underscores.
  142.  *
  143.  * Usage/Warnings:  Should be bulletproof.  Exception code included to allow
  144.  *                  the special file name '..' through.
  145.  *
  146.  * Calls:
  147.  */
  148.  
  149. VOID Convert_to_8dot3(CHAR *szLong,CHAR *szFat)
  150. {
  151.     USHORT usStemMaxLen; /* Holds the max size the 8 char base can be */
  152.     USHORT cnt;
  153.     CHAR   szStem[9],szExt[4];  /* Holds the Stem and Extension */
  154.     CHAR   *szLastDot;          /* Pointer to the last dot */
  155.  
  156.     if(!strcmp(szLong,"..")) /* Allow the predecessor file to pass thru */
  157.     {
  158.         strcpy(szFat,"..");
  159.         return;
  160.     }
  161.  
  162.     szLastDot = strrchr(szLong,'.'); /* Find the last period */
  163.  
  164.     if(szLastDot)  /* There is at least one period */
  165.     {
  166.         strncpy(szExt,szLastDot+1,3);       /* 1st 3 chars after . are ext */
  167.         szExt[3]=0;
  168.         usStemMaxLen = szLastDot - szLong;  /* Max stem is everything b4 . */
  169.     }
  170.     else
  171.     {
  172.         *szExt = 0;                         /* No extension */
  173.         usStemMaxLen = strlen(szLong);      /* Stem can be whole string */
  174.     }
  175.  
  176.     if(usStemMaxLen>8)                      /* Limit stem to 8 chars */
  177.         usStemMaxLen = 8;
  178.  
  179.     for(cnt=0;cnt<usStemMaxLen;cnt++)       /* Copy in chars to form stem */
  180.     {
  181.         switch(szLong[cnt])
  182.         {
  183.             case '.':                       /* Convert .'s to _'s */
  184.                 szStem[cnt] = '_';
  185.                 break;
  186.             default:                        /* Copy all other chars */
  187.                 szStem[cnt] = szLong[cnt];
  188.                 break;
  189.         }
  190.     }
  191.     szStem[cnt] = 0;
  192.  
  193.     /* Put it all together */
  194.     strcpy(szFat,szStem);
  195.     strcat(szFat,".");
  196.     strcat(szFat,szExt);
  197. }
  198.  
  199.  
  200. /*
  201.  * Function name: ParsePathName()
  202.  *
  203.  * Parameters:  szFullPath points to the input full path name.
  204.  *              szDrive points to the return buffer for the drive letter.
  205.  *              szPath points to the return buffer for the path.
  206.  *              szFilename points to the return buffer for the Filename.
  207.  *
  208.  * Returns: VOID. The converted string is placed in last 3 passed params.
  209.  *
  210.  * Purpose: Break a full path string and break it into its three components.
  211.  *          If the passed string doesn't have a drive, the current letter is
  212.  *          fetched an placed in the return buffer.  The same is true for
  213.  *          the path buffer.
  214.  *
  215.  * Usage/Warnings:  Error checking should be done on the DOS calls.
  216.  *
  217.  * Calls:
  218.  */
  219.  
  220. VOID ParsePathName(CHAR *szFullPath,CHAR *szDrive,CHAR *szPath,CHAR *szFilename)
  221. {
  222.     CHAR *szBack;          /* Used to find last backslach */
  223.     USHORT usPathLen;      /* Holds the length of the path part of string */
  224.  
  225.     *szPath = *szFilename = 0;
  226.  
  227.     /* Do the Drive letter */
  228.     if(*(szFullPath+1)==':')           /* If there is a drive letter */
  229.     {
  230.         szDrive[0] = *szFullPath;
  231.  
  232.         szFullPath += 2;
  233.     }
  234.     else                               /* We take the default */
  235.     {
  236.         USHORT dno;  /* Drive number */
  237.         ULONG  dmap; /* Map of available drives */
  238.  
  239.         DosQCurDisk((PUSHORT) &dno,(PULONG) &dmap);
  240.         *szDrive = (CHAR)( dno + 'A'-1);
  241.     }
  242.     szDrive[1] = ':';          /* Add the colon */
  243.     szDrive[2] = (CHAR) 0;
  244.  
  245.     /* Now do the path */
  246.     szBack = strrchr(szFullPath,'\\');
  247.     if(szBack)                         /* There is at least 1 backslash */
  248.     {
  249.        usPathLen = szBack - szFullPath + 1;
  250.        strncpy(szPath,szFullPath,usPathLen);   /* Copy path */
  251.        szPath[usPathLen] = (CHAR) 0;
  252.     }
  253.     else
  254.     {
  255.        *szPath = (CHAR) 0;
  256.        szBack  = szFullPath-1;  /* Points 1 char before the file name */
  257.     }
  258.  
  259.     /* Finally do the file name */
  260.     strcpy(szFilename,szBack+1);
  261. }
  262.  
  263.  
  264. /*
  265.  * Function name: QueryLongname()
  266.  *
  267.  * Parameters:  szfile points to the file to be queried.
  268.  *              szLong points to the return buffer for the long filename.
  269.  *
  270.  * Returns: VOID. The converted string is placed in last 3 passed params.
  271.  *
  272.  * Purpose: Looks for an EA named .LONGNAME attached to szfile.  If found,
  273.  *          it places the EA value in the return buffer.
  274.  *
  275.  * Usage/Warnings:  Routine assumes that the EA format is LP ASCII which
  276.  *                  is what the specs required, but probably the exception
  277.  *                  handling should be a bit tighter.  Return buf should be
  278.  *                  at least CCHMAXPATH long to accomodate max length names.
  279.  *                  Note also that no check is made to prevent overwriting
  280.  *                  the end of the return buffer.
  281.  *
  282.  * Calls:
  283.  */
  284.  
  285. VOID QueryLongname(CHAR *szfile,CHAR *szLong)
  286. {
  287.     CHAR    *szEAName;  /* Points to the .LONGNAME string */
  288.     SHORT   cbEAName;   /* Length of the .LONGNAME string */
  289.  
  290.     SHORT   cbFEAList;  /* The length of the FEA buf to be used */
  291.     SHORT   cbGEAList;  /* "                 GEA                */
  292.  
  293.     CHAR   cvFdump[300],cvGdump[50];     /* FEA and GEA buffers */
  294.     FEALIST *pFEAList;                   /* Pointers to the buffers */
  295.     GEALIST *pGEAList;
  296.     EAOP    eaop;
  297.                                          /* Pass struct for Dos call */
  298.     USHORT  usRetval;
  299.     SHORT   cbRet;
  300.     CHAR    *szT;
  301.  
  302.     *szLong = (CHAR) 0;                /* Default if we can't get the EA */
  303.  
  304.     szEAName = ".LONGNAME";        /* The particular EA we are interested in */
  305.     cbEAName = strlen(szEAName);
  306.  
  307.     cbGEAList = sizeof(GEALIST) + cbEAName;  /* Set buf lengths */
  308.     cbFEAList = sizeof(FEALIST) + cbEAName+1 + 256 + 2;
  309.  
  310.     pFEAList = (FEALIST *) cvFdump;   /* Set pointers to 2 buffers */
  311.     pGEAList = (GEALIST *) cvGdump;
  312.  
  313.     eaop.fpGEAList = (PGEALIST) pGEAList; /* Build the EAOP struct */
  314.     eaop.fpFEAList = (PFEALIST) pFEAList;
  315.  
  316.     pGEAList->cbList = cbGEAList;       /* Fill in GEA buf length */
  317.     pGEAList->list[0].cbName = (CHAR) cbEAName; /* Set .longname length */
  318.     strcpy((char *) pGEAList->list[0].szName, (char *) szEAName);
  319.  
  320.     pFEAList -> cbList = cbFEAList; /* Set length of receiving buffer */
  321.  
  322.     usRetval = DosQPathInfo(szfile,      /* Get the .LONGNAME EA */
  323.                             GetInfoLevel3,
  324.                             (PVOID) &eaop,
  325.                             sizeof(EAOP),
  326.                             0L);
  327.  
  328.     if(usRetval != 0) /* There was an error */
  329.        return;
  330.  
  331.     if(pFEAList->list[0].cbValue <=0)  /* It couldn't return EA value */
  332.        return;
  333.  
  334.     szT = (CHAR *) pFEAList + sizeof(FEALIST) + cbEAName + 1;
  335.     if (*((USHORT *) szT) == 0xfffd) /* length preceeded ASCII */
  336.     {
  337.         szT += 2;
  338.         cbRet = *((USHORT *) szT);
  339.  
  340.         szT += 2;
  341.         strncpy(szLong,szT,cbRet);
  342.         szLong[cbRet]=0;
  343.     }
  344. }
  345.  
  346.  
  347. /*
  348.  * Function name: QueryIFS()
  349.  *
  350.  * Parameters:  szDrive points to drive letter to be queried.
  351.  *              pusLocale will contain the location of the drive:
  352.  *                        3=local, 4=remote.
  353.  *              pusFSDName will contain the IFS type: 0=FAT, 1=HPFS, 2=Other.
  354.  *
  355.  * Returns: VOID.  All returns are in the last 2 params.
  356.  *
  357.  * Purpose: Mainly used to determine whether the file system is FAT or HPFS.
  358.  *          also returns info on whether the drive is local or remote.
  359.  *
  360.  * Usage/Warnings:  Error checking on the DOS call should be implemented.
  361.  *                  The buffer filled by DosQFSAttach is structured as follows:
  362.  *                         USHORT iType;
  363.  *                         USHORT cbName;
  364.  *                         UCHAR  szName[];
  365.  *                         USHORT cbFSDName;
  366.  *                         UCHAR  szFSDName[];
  367.  *                         ...
  368.  *
  369.  * Calls:
  370.  */
  371.  
  372. VOID QueryIFS(CHAR *szDrive,PUSHORT pusLocale,PUSHORT pusFSDName)
  373. {
  374.     CHAR vChunk[100];             /* Buffer for data from DosQFSAttach */
  375.     USHORT usChunkLen=100;
  376.     USHORT usTemp;                /* Holds offset for FSDName */
  377.  
  378.     DosQFSAttach(szDrive,0,GetInfoLevel1, vChunk,&usChunkLen,0L);
  379.  
  380.     *pusLocale = *((PUSHORT) vChunk);  /* Set local from 1st USHORT *);*/
  381.  
  382.     /* Skip over iType, cbName, szName, and cbFSDName fields to szFSDName */
  383.     usTemp = *((PUSHORT) &vChunk[sizeof(USHORT)]) + sizeof(USHORT)*3 + 1;
  384.  
  385.     if(!strcmp("FAT",&vChunk[usTemp]))
  386.     {
  387.         *pusFSDName = 0;
  388.         return;
  389.     }
  390.     if(!strcmp("HPFS",&vChunk[usTemp]))
  391.     {
  392.         *pusFSDName = 1;
  393.         return;
  394.     }
  395.  
  396.     *pusFSDName = 2;
  397.     return;
  398. }
  399.  
  400. 
  401.