home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / CPP / METAKIT.ZIP / EXAMPLES / CATFISH / LFNAMES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-09  |  9.3 KB  |  329 lines

  1. // listing 2, lfnames.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <dos.h>
  5. #include <io.h>
  6. #include <fcntl.h>
  7. #include <sys\stat.h>
  8. #include <string.h>
  9. #include <errno.h>
  10.  
  11. #include "lfnames.h"
  12.  
  13. // #define TEST  // defines main to make test program
  14.  
  15. #ifdef _MSC_VER
  16. #if (_MSC_VER>=600)
  17. #define SREGS _SREGS
  18. #define REGS  _REGS
  19. #define intdosx _intdosx
  20. #undef FP_OFF
  21. #undef FP_SEG
  22. // need to do this for MSC, because the MSC version requires
  23. // an Lvalue for the pointer!
  24. #define FP_OFF(p) (unsigned short)(p)
  25. #define FP_SEG(p) (unsigned short)((unsigned long)(void __far *)(p)>>16)
  26. #endif
  27. #endif
  28.  
  29. static int DoDosCall( unsigned func, union REGS *r, struct SREGS *s )
  30. // helper function to call DOS interrupt
  31. {
  32.    r->x.ax = func;
  33.    intdosx(r,r,s);
  34.    if(r->x.cflag)
  35.       _doserrno = r->x.ax;
  36.    else
  37.       _doserrno = 0;
  38.    return r->x.cflag;
  39. }
  40.  
  41. #define SETPTR(seg,off,ptr) s.seg = FP_SEG((ptr)), r.x.off = FP_OFF((ptr))
  42.  
  43. int lfn_api( const char *rootname )
  44. // returns non-zero if volume supports long file names
  45. {
  46.    union REGS r; struct SREGS s;
  47.    char filesystem[40];
  48.    SETPTR(es,di,filesystem);
  49.    r.x.cx = sizeof(filesystem);
  50.    SETPTR(ds,dx,rootname);
  51.    if(DoDosCall(0x71a0,&r,&s))
  52.       return 0;
  53.    return r.x.bx & 0x4000;  // check for FS_LFN_APIS flag
  54. }
  55.  
  56. unsigned GetShortPathName( const char *filename,
  57.               const char *shortname, unsigned size )
  58. {
  59.    union REGS r; struct SREGS s;
  60.    if(size<SFN_MAX_PATH)  // path too small?
  61.       return 0;
  62.    SETPTR(ds,si,filename);
  63.    SETPTR(es,di,shortname);
  64.    r.x.cx = 1;
  65.    if(DoDosCall(0x7160,&r,&s))
  66.       return 0;
  67.    return strlen(shortname);
  68. }
  69.  
  70. unsigned GetLongPathName( const char *filename,
  71.               const char *longname, unsigned size )
  72. {
  73.    union REGS r; struct SREGS s;
  74.    if(size<LFN_MAX_PATH)  // path too small?
  75.       return 0;
  76.    SETPTR(ds,si,filename);
  77.    SETPTR(es,di,longname);
  78.    r.x.cx = 2;
  79.    if(DoDosCall(0x7160,&r,&s))
  80.       return 0;
  81.    return strlen(longname);
  82. }
  83.  
  84. int lfn_mkdir( const char *path )
  85. {
  86.    union REGS r; struct SREGS s;
  87.    SETPTR(ds,dx,path);
  88.    if(DoDosCall(0x7139,&r,&s))
  89.      return -1;
  90.    return 0;
  91. }
  92.  
  93. int lfn_rmdir( const char *path )
  94. {
  95.    union REGS r; struct SREGS s;
  96.    SETPTR(ds,dx,path);
  97.    if(DoDosCall(0x713a,&r,&s))
  98.      return -1;
  99.    return 0;
  100. }
  101.  
  102. int lfn_chdir( const char *path )
  103. {
  104.    union REGS r; struct SREGS s;
  105.    SETPTR(ds,dx,path);
  106.    if(DoDosCall(0x713b,&r,&s))
  107.       return -1;
  108.    return 0;
  109. }
  110.  
  111. int lfn_unlink( const char *path )
  112. {
  113.    union REGS r; struct SREGS s;
  114.    SETPTR(ds,dx,path);
  115.    r.h.cl = _A_ARCH|_A_SYSTEM|_A_RDONLY;
  116.    r.h.ch = 0; // must match
  117.    r.x.si = 0; // no wild cards
  118.    if(DoDosCall(0x7141,&r,&s))
  119.      return -1;
  120.    return 0;
  121. }
  122.  
  123. int lfn_rename( const char *oldname, const char *newname )
  124. {
  125.    union REGS r; struct SREGS s;
  126.    SETPTR(ds,dx,oldname);
  127.    SETPTR(es,di,newname);
  128.    if(DoDosCall(0x7156,&r,&s))
  129.       return -1;
  130.    return 0;
  131. }
  132.  
  133. int lfn_access( const char *path, int amode )
  134. {
  135.    union REGS r; struct SREGS s;
  136.    r.x.bx = 0;       // get extended attributes
  137.    SETPTR(ds,dx,path);
  138.    if(DoDosCall(0x7143,&r,&s))
  139.       return -1;
  140.    if(!(amode&0x02) || !(r.x.cx & _A_RDONLY) )
  141.       return 0;
  142.    errno = EACCES;
  143.    return -1;
  144. }
  145.  
  146. typedef unsigned long DWORD;
  147.  
  148. typedef struct _FILETIME {
  149.    DWORD dwLowDateTime;
  150.    DWORD dwHighDateTime;
  151. } FILETIME;
  152.  
  153. typedef struct _WIN32_FIND_DATA { // wfd
  154.    DWORD dwFileAttributes;
  155.    FILETIME ftCreationTime;
  156.    FILETIME ftLastAccessTime;
  157.    FILETIME ftLastWriteTime;
  158.    DWORD    nFileSizeHigh;
  159.    DWORD    nFileSizeLow;
  160.    DWORD    dwReserved0;
  161.    DWORD    dwReserved1;
  162.    char     cFileName[ LFN_MAX_PATH ];
  163.    char    cAlternateFileName[ 14 ];
  164. } WIN32_FIND_DATA;
  165.  
  166. int lfn_findfirst( const char *path, int attrib, struct lfn_find_t *finfo )
  167. {
  168.    WIN32_FIND_DATA finddata;
  169.    union REGS r; struct SREGS s;
  170.    SETPTR(ds,dx,path);
  171.    SETPTR(es,di,&finddata);
  172.    r.x.cx = attrib;
  173.    r.x.si = 1; // MS-DOS format time/date
  174.    if(DoDosCall(0x714e,&r,&s))
  175.       return -1;
  176.    finfo->findhandle = r.x.ax;  // save find handle
  177.    strcpy(finfo->name,finddata.cFileName);
  178.    finfo->size = finddata.nFileSizeLow;
  179.    finfo->wr_date =
  180.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime >> 16 );
  181.    finfo->wr_time =
  182.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime & 0xffff );
  183.    finfo->attrib = finddata.dwFileAttributes & 0x7f;
  184.    return 0;
  185. }
  186.  
  187. int lfn_findnext( struct lfn_find_t *finfo )
  188. {
  189.    WIN32_FIND_DATA finddata;
  190.    union REGS r; struct SREGS s;
  191.    SETPTR(es,di,&finddata);
  192.    r.x.si = 1; // use dos time
  193.    r.x.bx = finfo->findhandle;
  194.    if(DoDosCall(0x714f,&r,&s))
  195.       return -1;
  196.    strcpy(finfo->name,finddata.cFileName);
  197.    finfo->size = finddata.nFileSizeLow;
  198.    finfo->wr_date =
  199.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime >> 16);
  200.    finfo->wr_time =
  201.       (unsigned)(finddata.ftLastWriteTime.dwLowDateTime & 0xffff );
  202.    finfo->attrib = finddata.dwFileAttributes & 0x7f;
  203.    return 0;
  204. }
  205.  
  206. void lfn_findclose( struct lfn_find_t *finfo )
  207. {
  208.    union REGS r; struct SREGS s;
  209.    r.x.bx = finfo->findhandle;
  210.    DoDosCall(0x71a1,&r,&s);
  211. }
  212.  
  213. int lfn_open( const char *path, int mode, int smode )
  214. {
  215.    union REGS r; struct SREGS s;
  216.    SETPTR(ds,si,path);
  217.    r.x.bx = mode & 0x3; // read/write flags
  218.    if(mode & O_CREAT) {
  219.       switch(smode&(S_IREAD|S_IWRITE)) {
  220.          case 0:
  221.             r.x.bx |= 0x0010; // deny read/write
  222.             break;
  223.          case S_IREAD:
  224.             r.x.bx |= 0x0020; // deny write
  225.             break;
  226.          case S_IWRITE:
  227.             r.x.bx |= 0x0030; // deny read
  228.             break;
  229.          case S_IWRITE|S_IREAD:
  230.             r.x.bx |= 0x0040; // deny none
  231.             break;
  232.       }
  233.    }
  234.    r.x.cx = _A_NORMAL;
  235.    r.x.dx = 0;
  236.    if(mode & O_CREAT ) r.x.dx |= 0x0010;
  237.    if(mode & O_TRUNC ) r.x.dx |= 0x0002;
  238.    if(mode & O_EXCL ) r.x.dx |= 0x0001;  // file must exist
  239.    if(DoDosCall(0x716c,&r,&s))
  240.       return -1;
  241.    return r.x.ax;  // return file handle
  242. }
  243.  
  244. FILE *lfn_fopen( const char *filename, const char *mode )
  245. {
  246.    char shortname[LFN_MAX_PATH];
  247.    if( strchr(mode,'a') || strchr(mode,'w') ) {
  248.       // if the file doesn't exist - create it
  249.       if( lfn_access(filename,00) ) {
  250.          int hf = lfn_open(filename,O_CREAT|O_TRUNC|O_WRONLY,0);
  251.          close(hf);
  252.       }
  253.    } // convert a long name to a short name, if needed
  254.    GetShortPathName(filename,shortname,sizeof(shortname));
  255.    return fopen(shortname,mode);
  256. }
  257.  
  258. #ifdef TEST
  259. int main( int argc, char **argv )
  260. {
  261.    if(argc>2) {
  262.       if( strcmpi(argv[1],"api")==0 ) {
  263.          printf("Long filenames are %savailable for \"%s\".\n",
  264.             lfn_api(argv[2])?"":"not ",argv[2]);
  265.       } else if( strcmpi(argv[1],"shortname")==0 ) {
  266.          char buf[SFN_MAX_PATH];
  267.          if( GetShortPathName(argv[2],buf,sizeof(buf)) ) {
  268.             printf("The short name of %s is %s.\n",argv[2],buf);
  269.             {
  270.                int i;
  271.                for(i=0;i<strlen(buf);i++)
  272.                   printf("'%c' %02x ",buf[i],buf[i]);
  273.             }
  274.          } else
  275.             printf("Unable to convert to %s to a short name.\n",
  276.                argv[2]);
  277.       } else if( strcmpi(argv[1],"longname")==0 ) {
  278.          char buf[LFN_MAX_PATH];
  279.          if( GetLongPathName(argv[2],buf,sizeof(buf)) )
  280.             printf("The long name of \"%s\" is \"%s\".\n",argv[2],buf);
  281.          else
  282.             printf("Unable to convert to \"%s\" to a long name.\n",
  283.                argv[2]);
  284.       } else if( strcmpi(argv[1],"mkdir")==0) {
  285.          if( lfn_mkdir(argv[2]) )
  286.             printf("dos error %d\n",_doserrno);
  287.       } else if( strcmpi(argv[1],"chdir")==0) {
  288.          if( lfn_chdir(argv[2]) )
  289.             printf("dos error %d\n",_doserrno);
  290.       } else if( strcmpi(argv[1],"rmdir")==0) {
  291.          if( lfn_rmdir(argv[2]) )
  292.             printf("dos error %d\n",_doserrno);
  293.       } else if( strcmpi(argv[1],"exist")==0) {
  294.          printf("The file \"%s\" does %sexist.\n",
  295.             argv[2],lfn_access(argv[2],0)?"not ":"");
  296.       } else if( strcmpi(argv[1],"del")==0) {
  297.          if( lfn_unlink(argv[2]) )
  298.             printf("dos error %d\n",_doserrno);
  299.       } else if( strcmpi(argv[1],"readfile")==0 ) {
  300.          FILE *f = lfn_fopen(argv[2],"rb");
  301.          if(f) {
  302.             fseek(f,0,SEEK_END);
  303.             printf("The size of \"%s\" is %ld.\n",argv[2],ftell(f));
  304.             fclose(f);
  305.          } else
  306.             printf("Failed to open \"%s\".\n",argv[2]);
  307.       } else if( strcmpi(argv[1],"writefile")==0 ) {
  308.           FILE *f = lfn_fopen(argv[2],"w");
  309.           if(f) {
  310.              fprintf(f,"This file is named \"%s\"\n",argv[2]);
  311.              fclose(f);
  312.           } else
  313.              printf("Failed to open \"%s\".\n",argv[2]);
  314.       } else if( strcmpi(argv[1],"dir")==0 ) {
  315.          struct lfn_find_t f; int i;
  316.          for(i=lfn_findfirst(argv[2],_A_NORMAL,&f); i==0; i=lfn_findnext(&f) )
  317.              printf("%s %d/%d/%d %02d:%02d:%02d %lu\n",f.name,
  318.                    (f.wr_date>>5)&0xf,f.wr_date&0x1f,(f.wr_date>>9)+1980,
  319.                    f.wr_time>>11,(f.wr_time>>5)&0x3f,(f.wr_time&0x1f)*2,
  320.                    f.size);
  321.          lfn_findclose(&f);
  322.       } else
  323.          printf("unrecognized command %s\n",argv[1]);
  324.    } else
  325.       printf("syntax: lfnames cmd filename\n");
  326.    return 0;
  327. }
  328. #endif
  329.