⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cio.c

📁 一个使用IPX协议在两台机器间传送文件的程序
💻 C
字号:
/*

   CIO.C

   compatible direct access

   (c) 1996 Oliver Kraus

   kraus@lrs.e-technik.uni-erlangen.de

*/

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "ccommon.h"

/*--- ms-dos ---*/

#ifdef C_DOS

#include <stdio.h>   /* sprintf */
#include <direct.h>
#include <ctype.h>
#include <sys\stat.h>
#include <sys\types.h>
#include <fcntl.h>
#include <io.h>
#include <dos.h>

#include "dpmicall.h"

short c_pathbuf_sel_dir;
short c_pathbuf_seg_dir;
int c_pathbuf_is_dos_mem = 0;


/*
   returns name of filesystem ("FAT", ...)
   fills flags:
   Bit(s)   Description (Table 1083)
    0 searches are case sensitive
    1 preserves case in directory entries
    2 uses Unicode characters in file and directory names
    3-13 reserved (0)
    14   supports DOS long filename functions
    15   volume is compressed
*/
char *c_get_vol_info(const char *root, int *flags)
{
   static char s[64];
   rminfo_struct rmi;
   short sel_root, seg_root;
   short sel_sys, seg_sys;

   if ( dpmi_alloc_dos_memory(strlen(root)+1, &sel_root, &seg_root ) == 0 )
      return NULL;
   if ( dpmi_alloc_dos_memory(64, &sel_sys, &seg_sys ) == 0 )
   {
      dpmi_free_dos_memory(sel_root);
      return NULL;
   }

   dpmi_copy_to_dos(sel_root, (void *)root, strlen(root)+1);

   rmi.eax = 0x071a0L;
   rmi.ebx = 0UL;
   rmi.ecx = 64UL;
   rmi.edx = 0UL;

   rmi.ds = seg_root;
   rmi.esi = 0L;
   rmi.es = seg_sys;
   rmi.edi = 0L;

   if ( dpmi_simulate_rmi(0x021, &rmi) != 0 )
   {
      dpmi_free_dos_memory(sel_root);
      dpmi_free_dos_memory(sel_sys);
      return NULL;
   }

   dpmi_copy_from_dos(sel_sys, s, 64);

   if ( flags != NULL )
   {
      *flags = (int)rmi.ebx;
   }

   dpmi_free_dos_memory(sel_root);
   dpmi_free_dos_memory(sel_sys);
   return s;
}

/* 0: current, 1: A:\, 2: B:\, 3:C:\ etc */
int c_is_long_filename(int drive)
{
   static int is_long_filename[26] =
   { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     2, 2, 2, 2, 2, 2 };

   if ( drive == 0 )
      drive = c_getdrive();
   else
      drive--;

   if ( is_long_filename[drive] >= 2 )
   {
      int flags;
      char s[8];

      sprintf(s, "%c:\\", (char)(drive+'A'));
      if ( c_get_vol_info(s, &flags) == NULL )
      {
         is_long_filename[drive] = 0;
      }
      else
      {
         if ( (flags & (1<<14)) == 0 )
            is_long_filename[drive] = 0;
         else
            is_long_filename[drive] = 1;
      }
   }
   /*
   if ( is_long_filename[drive] == 0 )
      printf("no lnf for drive %c\n", drive+'A');
   else
      printf("lnf for drive %c enabled\n", drive+'A');
   */
   return is_long_filename[drive];
}

/* 0 == 'A' */
void c_chdrive(int drive)
{
   rminfo_struct rmi;

   rmi.eax = 0x0e00UL;
   rmi.ebx = 0UL;
   rmi.ecx = 0UL;
   rmi.edx = (unsigned long)drive;

   if ( dpmi_simulate_rmi(0x021, &rmi) != 0 )
   {
      return;
   }

   return;
}

/* 0 == 'A' */
int c_getdrive(void)
{
   rminfo_struct rmi;

   rmi.eax = 0x01900UL;
   rmi.ebx = 0UL;
   rmi.ecx = 0UL;
   rmi.edx = 0UL;

   dpmi_simulate_rmi(0x021, &rmi);

   return (int)(rmi.eax&0x0ffUL);
}


static int c_chdir_lfn(const char *newdir)
{
   size_t len;
   rminfo_struct rmi;

   if ( c_pathbuf_is_dos_mem == 0 )
   {
      if ( dpmi_alloc_dos_memory(C_MAX_PATHNAME, &c_pathbuf_sel_dir, &c_pathbuf_seg_dir ) == 0 )
         return ENOMEM;
      c_pathbuf_is_dos_mem = 1;
   }
   len = strlen(newdir);
   if ( len+1 >= C_MAX_PATHNAME )
         return EINVAL;
   dpmi_copy_to_dos(c_pathbuf_sel_dir, (void *)newdir, len+1);

   rmi.eax = 0x0713bL;
   rmi.ebx = 0UL;
   rmi.ecx = 0UL;
   rmi.edx = 0UL;

   rmi.ds = c_pathbuf_seg_dir;
   rmi.edx = 0L;

   if ( dpmi_simulate_rmi(0x021, &rmi) != 0 )
   {
      return (int)rmi.eax;
   }

   return (int)0;
}

static int c_mkdir_lfn(const char *newdir)
{
   size_t len;
   rminfo_struct rmi;

   if ( c_pathbuf_is_dos_mem == 0 )
   {
      if ( dpmi_alloc_dos_memory(C_MAX_PATHNAME, &c_pathbuf_sel_dir, &c_pathbuf_seg_dir ) == 0 )
         return ENOMEM;
      c_pathbuf_is_dos_mem = 1;
   }
   len = strlen(newdir);
   if ( len+1 >= C_MAX_PATHNAME )
         return EINVAL;
   dpmi_copy_to_dos(c_pathbuf_sel_dir, (void *)newdir, len+1);

   rmi.eax = 0x07139L;
   rmi.ebx = 0UL;
   rmi.ecx = 0UL;
   rmi.edx = 0UL;

   rmi.ds = c_pathbuf_seg_dir;
   rmi.edx = 0L;

   if ( dpmi_simulate_rmi(0x021, &rmi) != 0 )
   {
      return (int)rmi.eax;
   }

   return (int)0;
}

static char *c_getcwd_lfn(char *s)
{
   rminfo_struct rmi;

   if ( c_pathbuf_is_dos_mem == 0 )
   {
      if ( dpmi_alloc_dos_memory(C_MAX_PATHNAME, &c_pathbuf_sel_dir, &c_pathbuf_seg_dir ) == 0 )
         return NULL;
      c_pathbuf_is_dos_mem = 1;
   }

   rmi.eax = 0x07147L;
   rmi.ebx = 0UL;
   rmi.ecx = 0UL;
   rmi.edx = 0UL;    /* current drive */

   rmi.ds = c_pathbuf_seg_dir;
   rmi.esi = 0L;

   if ( dpmi_simulate_rmi(0x021, &rmi) != 0 )
   {
      return NULL;
   }

   dpmi_copy_from_dos(c_pathbuf_sel_dir, (void *)s, C_MAX_PATHNAME);
   if ( s[0] == '\0' )
      return s;
   if ( s[1] == ':' )
      return s;
   if ( s[0] == '\\' )
   {
      s[0] = (char)(c_getdrive()+'A');
      s[1] = ':';
      dpmi_copy_from_dos(c_pathbuf_sel_dir, (void *)(s+2), C_MAX_PATHNAME-2);
   }
   else
   {
      s[0] = (char)(c_getdrive()+'A');
      s[1] = ':';
      s[2] = '\\';
      dpmi_copy_from_dos(c_pathbuf_sel_dir, (void *)(s+3), C_MAX_PATHNAME-3);
   }

   return s;
}

int c_open_lfn(const char *filename, int oflag, int pmode)
{
   size_t len;
   rminfo_struct rmi;

   if ( c_pathbuf_is_dos_mem == 0 )
   {
      if ( dpmi_alloc_dos_memory(C_MAX_PATHNAME, &c_pathbuf_sel_dir, &c_pathbuf_seg_dir ) == 0 )
      {
         /* errno = ENOMEM; */
         return -1;
      }
      c_pathbuf_is_dos_mem = 1;
   }
   len = strlen(filename);
   if ( len+1 >= C_MAX_PATHNAME )
   {
      /* errno = EINVAL; */
      return -1;
   }
   dpmi_copy_to_dos(c_pathbuf_sel_dir, (void *)filename, len+1);

   rmi.eax = 0x0716c;
   rmi.ebx = 0UL;
   rmi.ecx = 0UL;
   rmi.edx = 0UL;
   rmi.edi = 0UL; /* alias hint (not used) */

   rmi.ds = c_pathbuf_seg_dir;
   rmi.esi = 0UL;

   /*
   if ( (oflag & O_CREAT) != 0 && (oflag & O_TRUNC) != 0 )
      rmi.edx |= 0x005UL;
   else if ( (oflag & O_TRUNC) != 0 )
      rmi.edx |= 0x001UL;
   else if ( (oflag & O_CREAT) != 0 )
      rmi.edx |= 0x004UL;
   */

   /* O_BINARY ??? */

   if ( (oflag & O_CREAT) != 0 && (oflag & O_TRUNC) != 0 )
      rmi.edx |= 0x012UL;
   else if ( (oflag & O_TRUNC) != 0 )
      rmi.edx |= 0x002UL;
   else if ( (oflag & O_CREAT) != 0 )
      rmi.edx |= 0x011UL;
   else
      rmi.edx |= 0x001UL;

   if ( (oflag & O_WRONLY) != 0 )
      rmi.ebx |= 0x01UL;
   if ( (oflag & O_RDWR) != 0 )
      rmi.ebx |= 0x02UL;

   if ( dpmi_simulate_rmi(0x021, &rmi) == 0 )
   {
      switch((int)rmi.ecx)
      {
         case 1:
            /* puts("file open"); */
            break;
         case 2:
            /* puts("file created"); */
            break;
         case 3:
            /* puts("file replaced"); */
            break;
         default:
            /* printf("file unknown action %d\n", (int)rmi.ecx); */
            _dos_close((int)rmi.eax);
            return -1;
      }
      return (int)rmi.eax;
   }

   return -1;
}



int c_is_long_filename_by_path(const char *newdir)
{
   if ( newdir[0] == '\0' )
      return c_is_long_filename(0);
   if ( newdir[1] == '\0' )
      return c_is_long_filename(0);
   if ( newdir[1] != ':' )
      return c_is_long_filename(0);
   return c_is_long_filename(toupper((int)newdir[0])-'A'+1);
}

int c_chdir(const char *newdir)
{
   if ( strcmp( newdir, "." ) == 0 )
      return 0;
   if ( c_is_long_filename_by_path(newdir) != 0 )
      return c_chdir_lfn(newdir);
   return chdir(newdir);
}

int c_mkdir(const char *newdir)
{
   if ( strcmp( newdir, "." ) == 0 )
      return 0;
   if ( c_is_long_filename_by_path(newdir) != 0 )
      return c_mkdir_lfn(newdir);
   return mkdir(newdir);
}

int c_open(const char *filename, int oflag, int pmode)
{
   int handle = -1;
   if ( c_is_long_filename_by_path(filename) != 0 )
      handle = c_open_lfn(filename, oflag, pmode);
   else
   {

      if ( (oflag & O_CREAT) != 0 )
      {
         oflag &= ~O_CREAT;
         if ( _dos_creat(filename, oflag, &handle) != 0 )
            handle = -1;
      }
      else
      {
         if ( _dos_open(filename, oflag, &handle) != 0 )
            handle = -1;
      }
   }
   /* printf("c_open: handle %d\n", handle); */
   return handle;
}

int c_close(int fhandle)
{
   /* printf("c_close: handle %d\n", fhandle); */
   return _dos_close(fhandle);
}

/* #define C_WRITE_SIZE ((size_t)1024) */
#define C_WRITE_SIZE ((size_t)61440)
#define C_READ_SIZE C_WRITE_SIZE

long c_write(int fhandle, void *buffer, long count)
{
   long written = 0L;
   unsigned num;
   /* printf("c_write: handle %d\n", fhandle); */
   /* printf("c_write: count: %ld\n", count); */
   while( count > (long)(unsigned long)C_WRITE_SIZE )
   {
      num = 0;
      /* printf("c_write: count: %ld\n", count); */
      if ( _dos_write(fhandle, buffer, C_WRITE_SIZE, &num) != 0 )
      {
         /*
         perror("");
         printf("c_write: error exit: %ld\n", written);
         */
         return written+(long)(unsigned long)num;
      }
      buffer = ((char *)buffer) + C_WRITE_SIZE;
      written += (long)(unsigned long)num;
      count -= (long)(unsigned long)C_WRITE_SIZE;
   }
   num = 0;
   if ( _dos_write(fhandle, buffer, (unsigned)count, &num) != 0 )
   {
      /*
      perror("");
      printf("c_write: error exit: %ld\n", written);
      */
      return written+(long)(unsigned long)num;
   }
   written += (long)(unsigned long)num;
   /* printf("c_write: written: %ld\n", written); */
   return written;
}

long c_read(int fhandle, void *buffer, long count)
{
   long read = 0L;
   unsigned num;
   while( count > (long)(unsigned long)C_WRITE_SIZE )
   {
      num = 0;
      if ( _dos_read(fhandle, buffer, C_WRITE_SIZE, &num) != 0 )
      {
         return read+(long)(unsigned long)num;
      }
      buffer = ((char *)buffer) + C_WRITE_SIZE;
      read += (long)(unsigned long)num;
      count -= (long)(unsigned long)C_WRITE_SIZE;
   }
   num = 0;
   if ( _dos_read(fhandle, buffer, (unsigned)count, &num) != 0 )
   {
      return read+(long)(unsigned long)num;
   }
   read += (long)(unsigned long)num;
   return read;
}

char *c_getcwd(void)
{
   static char s[C_MAX_PATHNAME];
   if ( c_is_long_filename(0) != 0 )
   {
      /*
      printf("lfn: %s\n", c_getcwd_lfn(s));
      printf("normal: %s\n", getcwd(s,C_MAX_PATHNAME));
      */
      return c_getcwd_lfn(s);
   }
   return getcwd(s,C_MAX_PATHNAME);
}

void c_io_clear(void)
{
   if ( c_pathbuf_is_dos_mem != 0 )
   {
      dpmi_free_dos_memory(c_pathbuf_sel_dir);
   }
   c_pathbuf_is_dos_mem = 0;
}
#endif

/*--- unix ---*/

#ifdef C_UNIX
int c_chdir(const char *newdir)
{
   return chdir(newdir);
}

int c_mkdir(const char *newdir)
{
   return mkdir(newdir);
}

int c_open(const char *filename, int oflag, int pmode)
{
   return open(filename, oflag, pmode);
}

void c_io_clear(void)
{
}
#endif

/*--- common ---*/

char c_common_buf[C_MAX_PATHNAME];


void c_strncpy(char *dest, const char *src, size_t n)
{
   strncpy(dest, src, n);
   dest[n-1] = '\0';
}

/* 0 if successful */
int c_create_path(const char *path)
{
   char *s = c_common_buf;
   char *t;

   c_strncpy(s, path, C_MAX_PATHNAME);
   if ( *s == C_DELIMITER_CHAR )
   {
      c_chdir(C_DELIMITER_STR);
      s++;
   }
   t = strtok(s, C_DELIMITER_STR);
   for(;;)
   {
      if ( t == NULL )
         break;
      if ( *t == '\0' )
         break;
      /* printf("create path token: %s\n", t); */
      if ( c_chdir(t) != 0 )
      {
         if ( c_mkdir(t) != 0 )
         {
            printf("create error with %s\n", t);
            return -1;
         }
      }
      t = strtok(NULL, C_DELIMITER_STR);
   }
   /* printf("path %s ok\n", path); */
   return 0;
}

/* 0 if successful */
int c_set_path(const char *path)
{
   char *s = c_common_buf;
   char *t;
   c_strncpy(s, path, C_MAX_PATHNAME);
#ifdef C_DOS
   if ( s[0] != '\0')
   {
      if ( s[1] == ':' )
      {
         c_chdrive(toupper(s[0])-'A');
         s+=2;
      }
   }
#endif

   if ( *s == C_DELIMITER_CHAR )
   {
      c_chdir(C_DELIMITER_STR);
      s++;
   }
   t = strtok(s, C_DELIMITER_STR);
   for(;;)
   {
      if ( t == NULL )
         break;
      if ( *t == '\0' )
         break;
      if ( c_chdir(t) != 0 )
      {
         return -1;
      }
      t = strtok(NULL, C_DELIMITER_STR);
   }
   return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -