📄 cio.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 + -