diff --git a/docs/contrib.txt b/docs/contrib.txt index 42ac844..923014d 100644 --- a/docs/contrib.txt +++ b/docs/contrib.txt @@ -14,6 +14,8 @@ James Tabor (jimtabor@infohwy.com) Eric Biederman (ebiederm+eric@ccr.net) Tom Ehlert (tom.ehlert@ginko.de) Victor Vlasenko (victor_vlasenko@hotbox.ru) +Jeremy Davis (jeremyd@computer.org) +Martin Stromberg (ams@ludd.luth.se) Bart Oldeman (bart@dosemu.org) And last, but not least, a big thanx to Pasquale J. Villani diff --git a/docs/fdkernel.lsm b/docs/fdkernel.lsm index 80dae64..df31680 100644 --- a/docs/fdkernel.lsm +++ b/docs/fdkernel.lsm @@ -1,7 +1,7 @@ Begin3 Title: The FreeDOS Kernel -Version: 2.0.25.c -Entered-date: 17 Nov 2001 +Version: 2.0.27 +Entered-date: xx Aug 2002 Description: The FreeDOS Kernel. Keywords: kernel freedos dos msdos Author: (developers) diff --git a/docs/history.txt b/docs/history.txt index 9bb943d..600928b 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -9,10 +9,31 @@ * disabled fatal() in error.c * Disable the A20 line upon exec (int21/ah=4B). This is necessary for some brain-dead exepacked programs. - * removed unnecessary buffer fields + * removed unnecessary "BUFFERS" fields * proper check for network/non-existing drive for int25/26. * save more bytes on the stack at various places + * made the local registers for inthndlr.c "near" instead of "far". + * fix bug in strchr handling for fcbfns.c (FcbParseFname) ++ Changes Steffen (but changed a lot by Bart) + * new truename (Bart: but without mapPath() style struct) + * merge open/create functions into one extended open function + * also honor the sharing bits better for "open" + * use local 8+3 path names in fatfs.c; merge name+extension + into one array + * take care of filenames that start with ASCII 5: they should be + treated as starting with 0xe5 + * exploit the fact that the filenames are already "truenames", + i.e., fully qualified in fatfs.c. This simplifies parsing a lot. + Changes Bart + * make "if exist c:\dir\nul" working + * honor "do not inherit handle on exec" flag for "open". + * improve the FCB functions so that they set the critical error code + properly + * next_cluster returns "1" instead of DE_xxx in case of failure. + * create one function to do binary character IO (used for CLOCK$ + driver and character drivers such as CON) + * better handling of ABORT/FAIL + * merge all read and write functions * patchobj makefile correction * printf uses va_list etc. * quicker and more robust Watcom build @@ -33,7 +54,6 @@ merge as much as possible from DosExeLoader and DosComLoader (from Tom:) eliminate some structures in low memory * main.c: slightly cleanup "SHELL=" line parsing. - 2002 May 9 - Build 2026b -------- Bart Oldeman (bart@dosemu.org) + Changes Tom diff --git a/hdr/fat.h b/hdr/fat.h index 97703f6..4f4faba 100644 --- a/hdr/fat.h +++ b/hdr/fat.h @@ -54,7 +54,8 @@ static BYTE *fat_hRcsId = #define FEXT_SIZE 3 /* FAT deleted flag */ -#define DELETED 0xe5 /* if first char, delete file */ +#define DELETED '\x5' /* if first char, delete file */ +#define EXT_DELETED '\xe5' /* external deleted flag */ /* FAT cluster to physical conversion macros */ #define clus_add(cl_no) ((ULONG) (((ULONG) cl_no - 2L) \ @@ -81,8 +82,7 @@ static BYTE *fat_hRcsId = /* FAT file system directory entry */ struct dirent { - UBYTE dir_name[FNAME_SIZE]; /* Filename */ - UBYTE dir_ext[FEXT_SIZE]; /* Filename extension */ + char dir_name[FNAME_SIZE + FEXT_SIZE]; /* Filename + extension in FCB format */ UBYTE dir_attrib; /* File Attribute */ UBYTE dir_case; /* File case */ UBYTE dir_crtimems; /* Milliseconds */ diff --git a/hdr/sft.h b/hdr/sft.h index 98c5dcc..e1c1c35 100644 --- a/hdr/sft.h +++ b/hdr/sft.h @@ -106,7 +106,7 @@ typedef struct _sfttbl { #define SFT_MRDWR 0x0002 /* read/write bit */ #define SFT_MWRITE 0x0001 /* write bit */ #define SFT_MREAD 0x0000 /* ~ write bit */ -#define SFT_OMASK 0x00f3 /* valid open mask */ +#define SFT_OMASK 0xfff3 /* valid open mask */ /* flag bits */ diff --git a/hdr/stacks.inc b/hdr/stacks.inc index 70a8763..383a221 100644 --- a/hdr/stacks.inc +++ b/hdr/stacks.inc @@ -117,13 +117,15 @@ irp_hi equ 26 ; later ; ; assumption: -; we have never seen MSVC (our only I386 compiler) to use -; anything but eax,ecx, edx +; we have never seen MSVC to use anything but eax,ecx, edx ; so we only protect eax, ebx, ecx, edx to conserve stack space ; ; to save even more stack space, we save only HIGH part of regs ; at some expense of slower execution. it's easier anyway :-) ; +; WATCOM only uses FS: and GS: (using -zff and -zgf) and never +; any high part of the 386 registers +; %IFNDEF I386 @@ -141,6 +143,9 @@ irp_hi equ 26 %macro Protect386Registers 0 %ifdef WATCOM + push fs + push gs + %else ror eax,16 push ax ror eax,16 @@ -153,9 +158,6 @@ irp_hi equ 26 ror edx,16 push dx ror edx,16 - %else - push fs - push gs %endif %endmacro @@ -163,6 +165,9 @@ irp_hi equ 26 %macro Restore386Registers 0 %ifdef WATCOM + pop gs + pop fs + %else ror edx,16 pop dx ror edx,16 @@ -175,9 +180,6 @@ irp_hi equ 26 ror eax,16 pop ax ror eax,16 - %else - pop gs - pop fs %endif %endmacro diff --git a/kernel/chario.c b/kernel/chario.c index 1cef021..3f3f53c 100644 --- a/kernel/chario.c +++ b/kernel/chario.c @@ -65,6 +65,40 @@ struct dhdr FAR *finddev(UWORD attr_mask) } #endif +UCOUNT BinaryCharIO(struct dhdr FAR * dev, UCOUNT n, void FAR * bp, unsigned command, COUNT *err) +{ + *err = SUCCESS; + + FOREVER + { + CharReqHdr.r_length = sizeof(request); + CharReqHdr.r_command = command; + CharReqHdr.r_count = n; + CharReqHdr.r_trans = bp; + CharReqHdr.r_status = 0; + execrh(&CharReqHdr, dev); + if (CharReqHdr.r_status & S_ERROR) + { + charloop: + switch (char_error(&CharReqHdr, dev)) + { + case ABORT: + case FAIL: + *err = DE_INVLDACC; + return 0; + case CONTINUE: + break; + case RETRY: + continue; + default: + goto charloop; + } + } + break; + } + return CharReqHdr.r_count; +} + VOID _cso(COUNT c) { if (syscon->dh_attr & ATTR_FASTCON) @@ -72,7 +106,7 @@ VOID _cso(COUNT c) #if defined(__TURBOC__) _AL = c; __int__(0x29); -#else +#elif defined(I86) asm { mov al, byte ptr c; @@ -81,14 +115,7 @@ VOID _cso(COUNT c) #endif return; } - CharReqHdr.r_length = sizeof(request); - CharReqHdr.r_command = C_OUTPUT; - CharReqHdr.r_count = 1; - CharReqHdr.r_trans = (BYTE FAR *) (&c); - CharReqHdr.r_status = 0; - execrh((request FAR *) & CharReqHdr, syscon); - if (CharReqHdr.r_status & S_ERROR) - char_error(&CharReqHdr, syscon); + BinaryCharIO(syscon, 1, &c, C_OUTPUT, &UnusedRetVal); } VOID cso(COUNT c) @@ -97,7 +124,7 @@ VOID cso(COUNT c) con_hold(); if (PrinterEcho) - DosWrite(STDPRN, 1, (BYTE FAR *) & c, (COUNT FAR *) & UnusedRetVal); + DosWrite(STDPRN, 1, (BYTE FAR *) & c, & UnusedRetVal); switch (c) { @@ -125,7 +152,7 @@ VOID cso(COUNT c) VOID sto(COUNT c) { - DosWrite(STDOUT, 1, (BYTE FAR *) & c, (COUNT FAR *) & UnusedRetVal); + DosWrite(STDOUT, 1, (BYTE FAR *) & c, & UnusedRetVal); } VOID mod_cso(REG UCOUNT c) @@ -176,14 +203,7 @@ COUNT con_read(void) { BYTE c; - CharReqHdr.r_length = sizeof(request); - CharReqHdr.r_command = C_INPUT; - CharReqHdr.r_count = 1; - CharReqHdr.r_trans = (BYTE FAR *) & c; - CharReqHdr.r_status = 0; - execrh((request FAR *) & CharReqHdr, syscon); - if (CharReqHdr.r_status & S_ERROR) - char_error(&CharReqHdr, syscon); + BinaryCharIO(syscon, 1, &c, C_INPUT, &UnusedRetVal); if (c == CTL_C) handle_break(); return c; @@ -216,9 +236,8 @@ UCOUNT _sti(BOOL check_break) Do_DosIdle_loop(); if (check_break) con_hold(); - while (GenericRead - (STDIN, 1, (BYTE FAR *) & c, (COUNT FAR *) & UnusedRetVal, - TRUE) != 1) ; + while (BinaryRead(STDIN, &c, & UnusedRetVal) != 1) + ; return c; } diff --git a/kernel/dosfns.c b/kernel/dosfns.c index 04159e5..c2d3803 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -35,11 +35,6 @@ static BYTE *dosfnsRcsId = #include "globals.h" -COUNT get_free_hndl(VOID); -sft FAR * get_free_sft(COUNT *); - -f_node_ptr xlt_fd(COUNT); - /* /// Added for SHARE. - Ron Cemer */ BYTE share_installed = 0; @@ -50,7 +45,7 @@ BYTE share_installed = 0; error. If < 0 is returned, it is the negated error return code, so DOS simply negates this value and returns it in AX. */ -STATIC int share_open_check(char far * filename, /* far pointer to fully qualified filename */ +STATIC int share_open_check(char * filename, /* pointer to fully qualified filename */ unsigned short pspseg, /* psp segment address of owner process */ int openmode, /* 0=read-only, 1=write-only, 2=read-write */ int sharemode); /* SHARE_COMPAT, etc... */ @@ -119,17 +114,13 @@ struct dpb FAR * GetDriveDPB(UBYTE drive, COUNT * rc) } #endif +/* Construct dir-style filename for ASCIIZ 8.3 name */ STATIC VOID DosGetFile(BYTE * lpszPath, BYTE FAR * lpszDosFileName) { - BYTE szLclName[FNAME_SIZE + 1]; - BYTE szLclExt[FEXT_SIZE + 1]; + char fcbname[FNAME_SIZE + FEXT_SIZE]; - ParseDosName(lpszPath, (COUNT *) 0, (BYTE *) 0, - szLclName, szLclExt, FALSE); - SpacePad(szLclName, FNAME_SIZE); - SpacePad(szLclExt, FEXT_SIZE); - fmemcpy(lpszDosFileName, (BYTE FAR *) szLclName, FNAME_SIZE); - fmemcpy(&lpszDosFileName[FNAME_SIZE], (BYTE FAR *) szLclExt, FEXT_SIZE); + ParseDosName(lpszPath, fcbname, FALSE); + fmemcpy(lpszDosFileName, fcbname, FNAME_SIZE + FEXT_SIZE); } sft FAR * idx_to_sft(COUNT SftIndex) @@ -146,6 +137,10 @@ sft FAR * idx_to_sft(COUNT SftIndex) { lpCurSft = (sft FAR *) & (sp->sftt_table[SftIndex]); + /* if not opened, the SFT is useless */ + if (lpCurSft->sft_count == 0) + return (sft FAR *) - 1; + /* finally, point to the right entry */ return lpCurSft; } @@ -153,6 +148,7 @@ sft FAR * idx_to_sft(COUNT SftIndex) SftIndex -= sp->sftt_count; } /* If not found, return an error */ + return (sft FAR *) - 1; } @@ -172,303 +168,173 @@ sft FAR *get_sft(UCOUNT hndl) return idx_to_sft(get_sft_idx(hndl)); } -/* - * The `force_binary' parameter is a hack to allow functions 0x01, 0x06, 0x07, - * and function 0x40 to use the same code for performing reads, even though the - * two classes of functions behave quite differently: 0x01 etc. always do - * binary reads, while for 0x40 the type of read (binary/text) depends on what - * the SFT says. -- ror4 - */ -UCOUNT GenericReadSft(sft FAR * s, UCOUNT n, BYTE FAR * bp, - COUNT FAR * err, BOOL force_binary) +UCOUNT DosRWSft(sft FAR * s, UCOUNT n, void FAR * bp, COUNT * err, int mode) { - UCOUNT ReadCount; - - /* Get the SFT block that contains the SFT */ - if (s == (sft FAR *) - 1) + *err = SUCCESS; + if (FP_OFF(s) == (size_t) - 1) { *err = DE_INVLDHNDL; return 0; } - - /* If not open or write permission - exit */ - if (s->sft_count == 0 || (s->sft_mode & SFT_MWRITE)) + /* If for read and write-only or for write and read-only then exit */ + if((mode == XFR_READ && (s->sft_mode & SFT_MWRITE)) || + (mode == XFR_WRITE && !(s->sft_mode & (SFT_MWRITE | SFT_MRDWR)))) { - *err = DE_INVLDACC; + *err = DE_ACCESS; return 0; } - + /* * Do remote first or return error. * must have been opened from remote. */ if (s->sft_flags & SFT_FSHARED) { - COUNT rc; + UCOUNT XferCount; BYTE FAR *save_dta; save_dta = dta; lpCurSft = s; current_filepos = s->sft_posit; /* needed for MSCDEX */ dta = bp; - ReadCount = remote_read(s, n, &rc); + XferCount = (mode == XFR_READ ? remote_read : remote_write)(s, n, err); dta = save_dta; - *err = rc; - return rc == SUCCESS ? ReadCount : 0; + return *err == SUCCESS ? XferCount : 0; } - /* Do a device read if device */ + + /* Do a device transfer if device */ if (s->sft_flags & SFT_FDEVICE) { - request rq; + if (mode==XFR_READ) + { + /* First test for eof and exit */ + /* immediately if it is */ + if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL)) + { + s->sft_flags &= ~SFT_FEOF; + return 0; + } + /* Now handle raw and cooked modes */ + if (s->sft_flags & SFT_FBINARY) + return BinaryCharIO(s->sft_dev, n, bp, C_INPUT, err); + if (s->sft_flags & SFT_FCONIN) + { + UCOUNT ReadCount; + + kb_buf.kb_size = LINESIZE - 1; + ReadCount = sti(&kb_buf); + if (ReadCount < kb_buf.kb_count) + s->sft_flags &= ~SFT_FEOF; + fmemcpy(bp, kb_buf.kb_buf, kb_buf.kb_count); + return ReadCount; + } + *(char FAR *)bp = _sti(FALSE); + return 1; + } + else + { + /* set to no EOF */ + s->sft_flags |= SFT_FEOF; + + /* if null just report full transfer */ + if (s->sft_flags & SFT_FNUL) + return n; + + /* Now handle raw and cooked modes */ + if (s->sft_flags & SFT_FBINARY) + { + n = BinaryCharIO(s->sft_dev, n, bp, C_OUTPUT, err); + if (n > 0 && (s->sft_flags & SFT_FCONOUT)) + { + UWORD cnt = n; + const char FAR *p = bp; + while (cnt--) + { + switch (*p++) + { + case CR: + scr_pos = 0; + break; + case LF: + case BELL: + break; + case BS: + --scr_pos; + break; + default: + ++scr_pos; + } + } + } + return n; + } + else + { + REG UWORD xfer; + const char FAR *p = bp; + + for (xfer = 0; xfer < n && *p != CTL_Z; p++, xfer++) + { + if (s->sft_flags & SFT_FCONOUT) + cso(*p); + else if (BinaryCharIO(s->sft_dev, 1, bp, C_OUTPUT, err) == 0 && + *err != SUCCESS) + return xfer; + if (control_break()) + { + handle_break(); + break; + } + } + return xfer; + } + } + } + + /* a block transfer */ + /* /// Added for SHARE - Ron Cemer */ + if (IsShareInstalled() && (s->sft_shroff >= 0)) + { + *err = share_access_check(cu_psp, s->sft_shroff, s->sft_posit, + (unsigned long)n, 1); + if (*err != SUCCESS) + return 0; + } + /* /// End of additions for SHARE - Ron Cemer */ + { + UCOUNT XferCount; + XferCount = rwblock(s->sft_status, bp, n, mode); + if (mode == XFR_WRITE) + s->sft_size = dos_getfsize(s->sft_status); + return XferCount; + } +} + +UCOUNT BinaryReadSft(sft FAR * s, void *bp, COUNT *err) +{ + if (FP_OFF(s) == (size_t) - 1) + { + *err = DE_INVLDHNDL; + return 0; + } + if (s->sft_mode & SFT_MWRITE) + { + *err = DE_INVLDACC; + return 0; + } + if (s->sft_flags & SFT_FDEVICE) + { /* First test for eof and exit */ /* immediately if it is */ if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL)) { s->sft_flags &= ~SFT_FEOF; - *err = SUCCESS; return 0; } - - /* Now handle raw and cooked modes */ - if (force_binary || (s->sft_flags & SFT_FBINARY)) - { - rq.r_length = sizeof(request); - rq.r_command = C_INPUT; - rq.r_count = n; - rq.r_trans = (BYTE FAR *) bp; - rq.r_status = 0; - execrh((request FAR *) & rq, s->sft_dev); - if (rq.r_status & S_ERROR) - { - char_error(&rq, s->sft_dev); - } - else - { - *err = SUCCESS; - return rq.r_count; - } - } - else if (s->sft_flags & SFT_FCONIN) - { - kb_buf.kb_size = LINESIZE - 1; - ReadCount = sti(&kb_buf); - if (ReadCount < kb_buf.kb_count) - s->sft_flags &= ~SFT_FEOF; - fmemcpy(bp, (BYTE FAR *) kb_buf.kb_buf, kb_buf.kb_count); - *err = SUCCESS; - return ReadCount; - } - else - { - *bp = _sti(FALSE); - *err = SUCCESS; - return 1; - } + return BinaryCharIO(s->sft_dev, 1, bp, C_INPUT, err); } - else - /* a block read */ - { - /* /// Added for SHARE - Ron Cemer */ - if (IsShareInstalled()) - { - if (s->sft_shroff >= 0) - { - int share_result = share_access_check(cu_psp, - s->sft_shroff, - s->sft_posit, - (unsigned long)n, - 1); - if (share_result != 0) - { - *err = share_result; - return 0; - } - } - } - /* /// End of additions for SHARE - Ron Cemer */ - - ReadCount = rwblock(s->sft_status, bp, n, XFR_READ); - *err = SUCCESS; - return ReadCount; - } - *err = SUCCESS; - return 0; -} - -#if 0 -UCOUNT DosRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err) -{ - return GenericRead(hndl, n, bp, err, FALSE); -} -#endif - -UCOUNT DosWriteSft(sft FAR * s, UCOUNT n, const BYTE FAR * bp, COUNT FAR * err) -{ - UCOUNT WriteCount; - - /* Get the SFT block that contains the SFT */ - if (s == (sft FAR *) - 1) - { - *err = DE_INVLDHNDL; - return 0; - } - - /* If this is not opened and it's not a write */ - /* another error */ - if (s->sft_count == 0 || - (!(s->sft_mode & SFT_MWRITE) && !(s->sft_mode & SFT_MRDWR))) - { - *err = DE_ACCESS; - return 0; - } - - if (s->sft_flags & SFT_FSHARED) - { - COUNT rc; - BYTE FAR *save_dta; - - save_dta = dta; - lpCurSft = s; - current_filepos = s->sft_posit; /* needed for MSCDEX */ - dta = (BYTE FAR *)bp; - WriteCount = remote_write(s, n, &rc); - dta = save_dta; - *err = rc; - return rc == SUCCESS ? WriteCount : 0; - } - - /* Do a device write if device */ - if (s->sft_flags & SFT_FDEVICE) - { - request rq; - - /* set to no EOF */ - s->sft_flags |= SFT_FEOF; - - /* if null just report full transfer */ - if (s->sft_flags & SFT_FNUL) - { - *err = SUCCESS; - return n; - } - - /* Now handle raw and cooked modes */ - if (s->sft_flags & SFT_FBINARY) - { - rq.r_length = sizeof(request); - rq.r_command = C_OUTPUT; - rq.r_count = n; - rq.r_trans = (BYTE FAR *) bp; - rq.r_status = 0; - execrh((request FAR *) & rq, s->sft_dev); - if (rq.r_status & S_ERROR) - { - char_error(&rq, s->sft_dev); - } - else - { - if (s->sft_flags & SFT_FCONOUT) - { - WORD cnt = rq.r_count; - while (cnt--) - { - switch (*bp++) - { - case CR: - scr_pos = 0; - break; - case LF: - case BELL: - break; - case BS: - --scr_pos; - break; - default: - ++scr_pos; - } - } - } - *err = SUCCESS; - return rq.r_count; - } - } - else - { - REG WORD xfer; - - for (xfer = 0; xfer < n && *bp != CTL_Z; bp++, xfer++) - { - if (s->sft_flags & SFT_FCONOUT) - { - cso(*bp); - } - else - FOREVER - { - rq.r_length = sizeof(request); - rq.r_command = C_OUTPUT; - rq.r_count = 1; - rq.r_trans = (BYTE FAR *)bp; - rq.r_status = 0; - execrh((request FAR *) & rq, s->sft_dev); - if (!(rq.r_status & S_ERROR)) - break; - charloop: - switch (char_error(&rq, s->sft_dev)) - { - case ABORT: - case FAIL: - *err = DE_INVLDACC; - return xfer; - case CONTINUE: - break; - case RETRY: - continue; - default: - goto charloop; - } - break; - } - if (control_break()) - { - handle_break(); - break; - } - } - *err = SUCCESS; - return xfer; - } - } - else - /* a block write */ - { - /* /// Added for SHARE - Ron Cemer */ - if (IsShareInstalled()) - { - if (s->sft_shroff >= 0) - { - int share_result = share_access_check(cu_psp, - s->sft_shroff, - s->sft_posit, - (unsigned long)n, - 1); - if (share_result != 0) - { - *err = share_result; - return 0; - } - } - } - /* /// End of additions for SHARE - Ron Cemer */ - - WriteCount = rwblock(s->sft_status, (BYTE FAR *)bp, n, XFR_WRITE); - s->sft_size = dos_getcufsize(s->sft_status); - *err = SUCCESS; - return WriteCount; - } - *err = SUCCESS; - return 0; + return DosRWSft(s, 1, bp, err, XFR_READ); } COUNT SftSeek(sft FAR * s, LONG new_pos, COUNT mode) @@ -537,27 +403,27 @@ COUNT SftSeek(sft FAR * s, LONG new_pos, COUNT mode) } } -COUNT DosSeek(COUNT hndl, LONG new_pos, COUNT mode, ULONG * set_pos) +ULONG DosSeek(COUNT hndl, LONG new_pos, COUNT mode) { sft FAR *s; COUNT result; /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) - return DE_INVLDHNDL; + return (ULONG)-1; result = SftSeek(s, new_pos, mode); if (result == SUCCESS) { - *set_pos = s->sft_posit; + return s->sft_posit; } - return result; + return (ULONG)-1; } -STATIC COUNT get_free_hndl(void) +STATIC long get_free_hndl(void) { psp FAR *p = MK_FP(cu_psp, 0); - WORD hndl; + unsigned hndl; for (hndl = 0; hndl < p->ps_maxfiles; hndl++) { @@ -598,18 +464,21 @@ sft FAR *get_free_sft(COUNT * sft_idx) return (sft FAR *) - 1; } -BYTE FAR *get_root(BYTE FAR * fname) +const char FAR *get_root(const char FAR * fname) { - BYTE FAR *froot; - REG WORD length; - /* find the end */ - for (length = 0, froot = fname; *froot != '\0'; ++froot) - ++length; + register unsigned length = fstrlen(fname) - 1; + char c; + /* now back up to first path seperator or start */ - for (--froot; length > 0 && !(*froot == '/' || *froot == '\\'); --froot) + while (length != (unsigned)-1) + { + c = fname[length]; + if (c == '/' || c == '\\' || c == ':') + break; --length; - return ++froot; + } + return fname + length + 1; } /* initialize SFT fields (for open/creat) for character devices */ @@ -633,15 +502,50 @@ STATIC void DeviceOpenSft(struct dhdr FAR *dhp, sft FAR *sftp) sftp->sft_dev = dhp; sftp->sft_date = dos_getdate(); sftp->sft_time = dos_gettime(); + sftp->sft_attrib = D_DEVICE; } -COUNT DosCreatSft(BYTE * fname, COUNT attrib) +/* +extended open codes +0000 0000 always fail +0000 0001 open O_OPEN +0000 0010 replace O_TRUNC + +0001 0000 create new file O_CREAT +0001 0001 create if not exists, open if exists O_CREAT | O_OPEN +0001 0010 create O_CREAT | O_TRUNC + +bits for flags (bits 11-8 are internal FreeDOS bits only) +15 O_FCB called from FCB open +14 O_SYNC commit for each write (not implemented yet) +13 O_NOCRIT do not invoke int23 (not implemented yet) +12 O_LARGEFILE allow files >= 2gb but < 4gb (not implemented yet) +11 O_LEGACY not called from int21/ah=6c: find right fn for redirector +10 O_CREAT if file does not exist, create it +9 O_TRUNC if file exists, truncate and open it \ not both +8 O_OPEN if file exists, open it / +7 O_NOINHERIT do not inherit handle on exec +6 \ +5 - sharing modes +4 / +3 reserved +2 bits 2,1,0 = 100: RDONLY and do not modify file's last access time + (not implemented yet) +1 \ 0=O_RDONLY, 1=O_WRONLY, +0 / 2=O_RDWR, 3=O_EXECCASE (preserve case for redirector EXEC, + (not implemented yet)) +*/ + +long DosOpenSft(char FAR * fname, unsigned flags, unsigned attrib) { COUNT sft_idx; sft FAR *sftp; struct dhdr FAR *dhp; - WORD result; - COUNT drive; + long result; + + result = truename(fname, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) + return result; /* now get a free system file table entry */ if ((sftp = get_free_sft(&sft_idx)) == (sft FAR *) - 1) @@ -649,56 +553,89 @@ COUNT DosCreatSft(BYTE * fname, COUNT attrib) fmemset(sftp, 0, sizeof(sft)); - sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */ sftp->sft_psp = cu_psp; - sftp->sft_mode = SFT_MRDWR; - sftp->sft_attrib = attrib; + sftp->sft_mode = flags & 0xf0ff; + OpenMode = (BYTE) flags; + + sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */ + sftp->sft_attrib = attrib = attrib | D_ARCHIVE; + + if (result & IS_NETWORK) + { + int status; + if ((flags & (O_TRUNC | O_CREAT)) == O_CREAT) + attrib |= 0x100; + lpCurSft = sftp; + if (!(flags & O_LEGACY)) + { + extern UWORD ASM ext_open_mode, ASM ext_open_attrib, ASM ext_open_action; + ext_open_mode = flags & 0x70ff; + ext_open_attrib = attrib & 0xff; + ext_open_action = ((flags & 0x0300) >> 8) | ((flags & O_CREAT) >> 6); + status = remote_extopen(sftp, attrib); + } + else if (flags & O_CREAT) + status = remote_creat(sftp, attrib); + else + status = remote_open(sftp, (BYTE)flags); + if (status >= SUCCESS) + { + if (sftp->sft_count == 0) + sftp->sft_count++; + return sft_idx | ((long)status << 16); + } + return status; + } + /* check for a device */ - dhp = IsDevice(fname); - if (dhp) + if ((result & IS_DEVICE) && (dhp = IsDevice(fname)) != NULL) { DeviceOpenSft(dhp, sftp); return sft_idx; } - if (current_ldt->cdsFlags & CDSNETWDRV) - { - lpCurSft = sftp; - result = remote_creat(sftp, attrib); - if (result == SUCCESS) - { - sftp->sft_count += 1; - return sft_idx; - } - return result; - } - - drive = get_verify_drive(fname); - if (drive < 0) - { - return drive; - } - /* /// Added for SHARE. - Ron Cemer */ if (IsShareInstalled()) { - if ((sftp->sft_shroff = share_open_check((char far *)fname, cu_psp, 0x02, /* read-write */ - 0)) < 0) /* compatibility mode */ + if ((sftp->sft_shroff = + share_open_check(PriPathName, cu_psp, + flags & 0x03, (flags >> 2) & 0x07)) < 0) return sftp->sft_shroff; } + /* /// End of additions for SHARE. - Ron Cemer */ - sftp->sft_status = dos_creat(fname, attrib); - if (sftp->sft_status >= 0) + /* NEVER EVER allow directories to be created */ + /* ... though FCB's are weird :) */ + if (!(flags & O_FCB) && + (attrib & ~(D_RDONLY | D_HIDDEN | D_SYSTEM | D_ARCHIVE | D_VOLID))) + return DE_ACCESS; + + result = dos_open(PriPathName, flags, attrib); + if (result >= 0) { + int status = (int)(result >> 16); + if (status == S_OPENED) + { + sftp->sft_attrib = dos_getfattr_fd((COUNT)result); + /* Check permissions. -- JPP + (do not allow to open volume labels/directories) */ + if (sftp->sft_attrib & (D_DIR | D_VOLID)) + { + dos_close((COUNT)result); + return DE_ACCESS; + } + sftp->sft_size = dos_getfsize((COUNT)result); + } + sftp->sft_status = (COUNT)result; + sftp->sft_flags = PriPathName[0] - 'A'; sftp->sft_count += 1; - sftp->sft_flags = drive; - DosGetFile(fname, sftp->sft_name); + DosGetFile(PriPathName, sftp->sft_name); dos_getftime(sftp->sft_status, (date FAR *) & sftp->sft_date, (time FAR *) & sftp->sft_time); - return sft_idx; + return sft_idx | ((long)status << 16); } else { @@ -709,49 +646,40 @@ COUNT DosCreatSft(BYTE * fname, COUNT attrib) sftp->sft_shroff = -1; } /* /// End of additions for SHARE. - Ron Cemer */ - return sftp->sft_status; - } + return result; + } } -COUNT DosCreat(BYTE FAR * fname, COUNT attrib) +long DosOpen(char FAR * fname, unsigned mode, unsigned attrib) { - psp FAR *p = MK_FP(cu_psp, 0); - COUNT sft_idx, hndl, result; - - /* NEVER EVER allow directories to be created */ - attrib = (BYTE) attrib; - if (attrib & ~(D_RDONLY | D_HIDDEN | D_SYSTEM | D_ARCHIVE)) - { - return DE_ACCESS; - } + long result; + unsigned hndl; + + /* test if mode is in range */ + if ((mode & ~SFT_OMASK) != 0) + return DE_INVLDACC; /* get a free handle */ - if ((hndl = get_free_hndl()) < 0) - return hndl; - - result = truename(fname, PriPathName, FALSE); - if (result != SUCCESS) - { + if ((result = get_free_hndl()) < 0) return result; - } + hndl = (unsigned)result; - sft_idx = DosCreatSft(PriPathName, attrib); + result = DosOpenSft(fname, mode, attrib); + if (result < SUCCESS) + return result; - if (sft_idx < SUCCESS) - return sft_idx; - - p->ps_filetab[hndl] = sft_idx; - return hndl; + ((psp FAR *)MK_FP(cu_psp, 0))->ps_filetab[hndl] = (UBYTE)result; + return hndl | (result & 0xffff0000l); } -COUNT CloneHandle(COUNT hndl) +COUNT CloneHandle(unsigned hndl) { - sft FAR *sftp; - /* now get the system file table entry */ - if ((sftp = get_sft(hndl)) == (sft FAR *) - 1) - return DE_INVLDHNDL; + sft FAR *sftp = get_sft(hndl); + if (sftp == (sft FAR *) -1 || (sftp->sft_mode & O_NOINHERIT)) + return DE_INVLDHNDL; + /* now that we have the system file table entry, get the fnode */ /* index, and increment the count, so that we've effectively */ /* cloned the file. */ @@ -759,37 +687,20 @@ COUNT CloneHandle(COUNT hndl) return SUCCESS; } -COUNT DosDup(COUNT Handle) +long DosDup(unsigned Handle) { - psp FAR *p = MK_FP(cu_psp, 0); - COUNT NewHandle; - sft FAR *Sftp; + long NewHandle; - /* Get the SFT block that contains the SFT */ - if ((Sftp = get_sft(Handle)) == (sft FAR *) - 1) - return DE_INVLDHNDL; - - /* If not open - exit */ - if (Sftp->sft_count <= 0) - return DE_INVLDHNDL; - - /* now get a free handle */ if ((NewHandle = get_free_hndl()) < 0) return NewHandle; - /* If everything looks ok, bump it up. */ - if ((Sftp->sft_flags & (SFT_FDEVICE | SFT_FSHARED)) - || (Sftp->sft_status >= 0)) - { - p->ps_filetab[NewHandle] = p->ps_filetab[Handle]; - Sftp->sft_count += 1; - return NewHandle; - } - else + if (DosForceDup(Handle, (unsigned)NewHandle) < 0) return DE_INVLDHNDL; + else + return NewHandle; } -COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle) +COUNT DosForceDup(unsigned OldHandle, unsigned NewHandle) { psp FAR *p = MK_FP(cu_psp, 0); sft FAR *Sftp; @@ -798,10 +709,6 @@ COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle) if ((Sftp = get_sft(OldHandle)) == (sft FAR *) - 1) return DE_INVLDHNDL; - /* If not open - exit */ - if (Sftp->sft_count <= 0) - return DE_INVLDHNDL; - /* now close the new handle if it's open */ if ((UBYTE) p->ps_filetab[NewHandle] != 0xff) { @@ -816,147 +723,21 @@ COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle) || (Sftp->sft_status >= 0)) { p->ps_filetab[NewHandle] = p->ps_filetab[OldHandle]; - + /* possible hazard: integer overflow ska*/ Sftp->sft_count += 1; - return NewHandle; + return SUCCESS; } else return DE_INVLDHNDL; } -COUNT DosOpenSft(BYTE * fname, COUNT mode) -{ - COUNT sft_idx; - sft FAR *sftp; - struct dhdr FAR *dhp; - COUNT drive, result; - - /* now get a free system file table entry */ - if ((sftp = get_free_sft(&sft_idx)) == (sft FAR *) - 1) - return DE_TOOMANY; - - fmemset(sftp, 0, sizeof(sft)); - sftp->sft_psp = cu_psp; - sftp->sft_mode = mode; - mode = OpenMode = (BYTE) mode; - - /* check for a device */ - dhp = IsDevice(fname); - if (dhp) - { - DeviceOpenSft(dhp, sftp); - return sft_idx; - } - - if (current_ldt->cdsFlags & CDSNETWDRV) - { - lpCurSft = sftp; - result = remote_open(sftp, mode); - /* printf("open SFT %d = %p\n",sft_idx,sftp); */ - if (result == SUCCESS) - { - sftp->sft_count += 1; - return sft_idx; - } - return result; - } - - drive = get_verify_drive(fname); - if (drive < 0) - { - return drive; - } - - sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */ - - /* /// Added for SHARE. - Ron Cemer */ - if (IsShareInstalled()) - { - if ((sftp->sft_shroff = share_open_check - ((char far *)fname, - (unsigned short)cu_psp, mode & 0x03, (mode >> 2) & 0x07)) < 0) - return sftp->sft_shroff; - } -/* /// End of additions for SHARE. - Ron Cemer */ - - sftp->sft_status = dos_open(fname, mode); - - if (sftp->sft_status >= 0) - { - f_node_ptr fnp = xlt_fd(sftp->sft_status); - - sftp->sft_attrib = fnp->f_dir.dir_attrib; - - /* Check permissions. -- JPP */ - if ((sftp->sft_attrib & (D_DIR | D_VOLID)) || - ((sftp->sft_attrib & D_RDONLY) && (mode != O_RDONLY))) - { - dos_close(sftp->sft_status); - return DE_ACCESS; - } - - sftp->sft_size = dos_getfsize(sftp->sft_status); - dos_getftime(sftp->sft_status, - (date FAR *) & sftp->sft_date, - (time FAR *) & sftp->sft_time); - sftp->sft_count += 1; - sftp->sft_mode = mode; - sftp->sft_flags = drive; - DosGetFile(fname, sftp->sft_name); - return sft_idx; - } - else - { -/* /// Added for SHARE *** CURLY BRACES ADDED ALSO!!! ***. - Ron Cemer */ - if (IsShareInstalled()) - { - share_close_file(sftp->sft_shroff); - sftp->sft_shroff = -1; - } -/* /// End of additions for SHARE. - Ron Cemer */ - return sftp->sft_status; - } -} - -COUNT DosOpen(BYTE FAR * fname, COUNT mode) -{ - psp FAR *p = MK_FP(cu_psp, 0); - COUNT sft_idx, result, hndl; - - /* test if mode is in range */ - if ((mode & ~SFT_OMASK) != 0) - return DE_INVLDACC; - - /* get a free handle */ - if ((hndl = get_free_hndl()) < 0) - return hndl; - - result = truename(fname, PriPathName, FALSE); - if (result != SUCCESS) - { - return result; - } - - sft_idx = DosOpenSft(PriPathName, mode & 3); - - if (sft_idx < SUCCESS) - return sft_idx; - - p->ps_filetab[hndl] = sft_idx; - return hndl; -} - COUNT DosCloseSft(WORD sft_idx, BOOL commitonly) { sft FAR *sftp = idx_to_sft(sft_idx); - if (sftp == (sft FAR *) - 1) + if (FP_OFF(sftp) == (size_t) - 1) return DE_INVLDHNDL; - /* If this is not opened another error */ - if (sftp->sft_count == 0) - return DE_ACCESS; - lpCurSft = sftp; /* remote sub sft_count. @@ -1004,8 +785,8 @@ COUNT DosClose(COUNT hndl) return ret; } -BOOL DosGetFree(UBYTE drive, UCOUNT FAR * spc, UCOUNT FAR * navc, - UCOUNT FAR * bps, UCOUNT FAR * nc) +BOOL DosGetFree(UBYTE drive, UWORD * spc, UWORD * navc, + UWORD * bps, UWORD * nc) { /* *nc==0xffff means: called from FatGetDrvData, fcbfns.c */ struct dpb FAR *dpbp; @@ -1050,12 +831,13 @@ BOOL DosGetFree(UBYTE drive, UCOUNT FAR * spc, UCOUNT FAR * navc, return TRUE; } - dpbp = CDSp[drive].cdsDpb; + dpbp = cdsp->cdsDpb; if (dpbp == NULL) return FALSE; if (*nc == 0xffff) { + /* hazard: no error checking! */ flush_buffers(dpbp->dpb_unit); dpbp->dpb_flags = M_CHANGED; } @@ -1104,8 +886,8 @@ BOOL DosGetFree(UBYTE drive, UCOUNT FAR * spc, UCOUNT FAR * navc, /* fake for 64k clusters do confuse some DOS programs, but let others work without overflowing */ *spc >>= 1; - *navc = (*navc < FAT_MAGIC16 / 2) ? (*navc << 1) : FAT_MAGIC16; - *nc = (*nc < FAT_MAGIC16 / 2) ? (*nc << 1) : FAT_MAGIC16; + *navc = ((unsigned)*navc < FAT_MAGIC16 / 2) ? ((unsigned)*navc << 1) : FAT_MAGIC16; + *nc = ((unsigned)*nc < FAT_MAGIC16 / 2) ? ((unsigned)*nc << 1) : FAT_MAGIC16; } return TRUE; } @@ -1166,31 +948,38 @@ COUNT DosGetExtFree(BYTE FAR * DriveString, struct xfreespace FAR * xfsp) COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s) { - BYTE FAR *cp; + BYTE *cp; + struct cds FAR *cdsp; /* next - "log" in the drive */ drive = (drive == 0 ? default_drive : drive - 1); /* first check for valid drive */ - if (drive >= lastdrive || !(CDSp[drive].cdsFlags & CDSVALID)) - { + if (drive >= lastdrive) return DE_INVLDDRV; - } - current_ldt = &CDSp[drive]; + cdsp = &CDSp[drive]; + fmemcpy(&TempCDS, cdsp, sizeof(TempCDS)); + if (!(TempCDS.cdsFlags & CDSVALID)) + return DE_INVLDDRV; + + cp = TempCDS.cdsCurrentPath; /* ensure termination of fstrcpy */ cp[MAX_CDSPATH - 1] = '\0'; - if ((current_ldt->cdsFlags & CDSNETWDRV) == 0) + if ((TempCDS.cdsFlags & CDSNETWDRV) == 0) { - if (current_ldt->cdsDpb == 0) - return DE_INVLDDRV; - - if ((media_check(current_ldt->cdsDpb) < 0)) - return DE_INVLDDRV; + /* dos_cd ensures that the path exists; if not, we + need to change to the root directory */ + int result = dos_cd(cdsp, cp); + if (result == DE_PATHNOTFND) + cp[TempCDS.cdsBackslashOffset + 1] = + cdsp->cdsCurrentPath[TempCDS.cdsBackslashOffset + 1] = '\0'; + else if (result < SUCCESS) + return result; } - cp = ¤t_ldt->cdsCurrentPath[current_ldt->cdsJoinOffset]; + cp += TempCDS.cdsBackslashOffset; if (*cp == '\0') s[0] = '\0'; else @@ -1202,7 +991,6 @@ COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s) #undef CHDIR_DEBUG COUNT DosChangeDir(BYTE FAR * s) { - REG COUNT drive; COUNT result; BYTE FAR *p; @@ -1211,20 +999,12 @@ COUNT DosChangeDir(BYTE FAR * s) if (*p == '*' || *p == '?') return DE_PATHNOTFND; - drive = get_verify_drive(s); - if (drive < 0) - { - return drive; - } - - result = truename(s, PriPathName, FALSE); - if (result != SUCCESS) + result = truename(s, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) { return result; } - current_ldt = &CDSp[drive]; - if (strlen(PriPathName) > sizeof(current_ldt->cdsCurrentPath) - 1) return DE_PATHNOTFND; @@ -1233,8 +1013,8 @@ COUNT DosChangeDir(BYTE FAR * s) #endif /* now get fs to change to new */ /* directory */ - result = (current_ldt->cdsFlags & CDSNETWDRV) ? remote_chdir() : - dos_cd(current_ldt, PriPathName); + result = (result & IS_NETWORK ? remote_chdir() : + dos_cd(current_ldt, PriPathName)); #if defined(CHDIR_DEBUG) printf("status = %04x, new_path='%Fs'\n", result, cdsd->cdsCurrentPath); #endif @@ -1266,7 +1046,10 @@ COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name) { COUNT rc; REG dmatch FAR *dmp = (dmatch FAR *) dta; - BYTE FAR *p; + + rc = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (rc < SUCCESS) + return rc; /* /// Added code here to do matching against device names. DOS findfirst will match exact device names if the @@ -1276,38 +1059,13 @@ COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name) in newstuff.c. - Ron Cemer */ - fmemset(dta, 0, sizeof(dmatch)); + fmemset(dmp, 0, sizeof(dmatch)); /* initially mark the dta as invalid for further findnexts */ - ((dmatch FAR *) dta)->dm_attr_fnd = D_DEVICE; + dmp->dm_attr_fnd = D_DEVICE; memset(&SearchDir, 0, sizeof(struct dirent)); - rc = truename(name, PriPathName, FALSE); - if (rc != SUCCESS) - return rc; - - if (IsDevice(PriPathName)) - { - COUNT i; - - /* Found a matching device. Hence there cannot be wildcards. */ - SearchDir.dir_attrib = D_DEVICE; - SearchDir.dir_time = dos_gettime(); - SearchDir.dir_date = dos_getdate(); - p = get_root(PriPathName); - memset(SearchDir.dir_name, ' ', FNAME_SIZE + FEXT_SIZE); - for (i = 0; i < FNAME_SIZE && *p && *p != '.'; i++) - SearchDir.dir_name[i] = *p++; - if (*p == '.') - p++; - for (i = 0; i < FEXT_SIZE && *p && *p != '.'; i++) - SearchDir.dir_ext[i] = *p++; - pop_dmp(dmp); - return SUCCESS; - } - /* /// End of additions. - Ron Cemer ; heavily edited - Bart Oldeman */ - SAttr = (BYTE) attr; #if defined(FIND_DEBUG) @@ -1315,19 +1073,38 @@ COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name) #endif fmemcpy(TempBuffer, dta, 21); - p = dta; - dta = (BYTE FAR *) TempBuffer; + dta = TempBuffer; - rc = current_ldt->cdsFlags & CDSNETWDRV ? - remote_findfirst((VOID FAR *) current_ldt) : - dos_findfirst(attr, PriPathName); + if (rc & IS_NETWORK) + rc = remote_findfirst(current_ldt); + else if (rc & IS_DEVICE) + { + const char *p; + COUNT i; - dta = p; + /* Found a matching device. Hence there cannot be wildcards. */ + SearchDir.dir_attrib = D_DEVICE; + SearchDir.dir_time = dos_gettime(); + SearchDir.dir_date = dos_getdate(); + p = (char *)FP_OFF(get_root(PriPathName)); + memset(SearchDir.dir_name, ' ', FNAME_SIZE + FEXT_SIZE); + for (i = 0; i < FNAME_SIZE && *p && *p != '.'; i++) + SearchDir.dir_name[i] = *p++; + if (*p == '.') + p++; + for (i = FNAME_SIZE; i < FNAME_SIZE + FEXT_SIZE && *p && *p != '.'; i++) + SearchDir.dir_name[i] = *p++; + rc = SUCCESS; + /* /// End of additions. - Ron Cemer ; heavily edited - Bart Oldeman */ + } + else + rc = dos_findfirst(attr, PriPathName); + dta = (char FAR *) dmp; fmemcpy(dta, TempBuffer, 21); - pop_dmp((dmatch FAR *) dta); + pop_dmp(dmp); if (rc != SUCCESS) - ((dmatch FAR *) dta)->dm_attr_fnd = D_DEVICE; /* mark invalid */ + dmp->dm_attr_fnd = D_DEVICE; /* mark invalid */ return rc; } @@ -1374,19 +1151,15 @@ COUNT DosFindNext(void) return rc; } -COUNT DosGetFtime(COUNT hndl, date FAR * dp, time FAR * tp) +COUNT DosGetFtime(COUNT hndl, date * dp, time * tp) { sft FAR *s; /*sfttbl FAR *sp;*/ /* Get the SFT block that contains the SFT */ - if ((s = get_sft(hndl)) == (sft FAR *) - 1) + if (FP_OFF(s = get_sft(hndl)) == (size_t) - 1) return DE_INVLDHNDL; - /* If this is not opened another error */ - if (s->sft_count == 0) - return DE_ACCESS; - /* If SFT entry refers to a device, return the date and time of opening */ if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED)) { @@ -1404,13 +1177,9 @@ COUNT DosSetFtimeSft(WORD sft_idx, date dp, time tp) /* Get the SFT block that contains the SFT */ sft FAR *s = idx_to_sft(sft_idx); - if (s == (sft FAR *) - 1) + if (FP_OFF(s) == (size_t) - 1) return DE_INVLDHNDL; - /* If this is not opened another error */ - if (s->sft_count == 0) - return DE_ACCESS; - /* If SFT entry refers to a device, do nothing */ if (s->sft_flags & SFT_FDEVICE) return SUCCESS; @@ -1428,42 +1197,30 @@ COUNT DosSetFtimeSft(WORD sft_idx, date dp, time tp) COUNT DosGetFattr(BYTE FAR * name) { - COUNT result, drive; + COUNT result; - if (IsDevice(name)) - { - return DE_FILENOTFND; - } - - drive = get_verify_drive(name); - if (drive < 0) - { - return drive; - } - - result = truename(name, PriPathName, FALSE); - if (result != SUCCESS) - { + result = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) return result; - } - + /* /// Added check for "d:\", which returns 0x10 (subdirectory) under DOS. - Ron Cemer */ - if ((PriPathName[0] != '\0') - && (PriPathName[1] == ':') - && ((PriPathName[2] == '/') || (PriPathName[2] == '\\')) - && (PriPathName[3] == '\0')) - { - return 0x10; - } + /* Theoretically: If the redirectory's qualify function + doesn't return nonsense this check can be reduced to + PriPathname[3] == 0, because local path names always + have the three-byte string ?:\ and UNC path shouldn't + validy consist of just two slashes. + -- 2001/09/03 ska*/ - current_ldt = &CDSp[drive]; - if (current_ldt->cdsFlags & CDSNETWDRV) - { + if (PriPathName[3] == '\0') + return 0x10; + + if (result & IS_NETWORK) return remote_getfattr(); - } - else - { + + if (result & IS_DEVICE) + return DE_FILENOTFND; + /* /// Use truename()'s result, which we already have in PriPathName. I copy it to tmp_name because PriPathName is global and seems to get trashed somewhere in transit. @@ -1492,39 +1249,26 @@ COUNT DosGetFattr(BYTE FAR * name) shit. tom */ - return dos_getfattr(PriPathName); - - } + return dos_getfattr(PriPathName); } +/* This function is almost identical to DosGetFattr(). + Maybe it is nice to join both functions. + -- 2001/09/03 ska*/ COUNT DosSetFattr(BYTE FAR * name, UWORD attrp) { - COUNT result, drive; + COUNT result; - if (IsDevice(name)) - { - return DE_FILENOTFND; - } - - drive = get_verify_drive(name); - if (drive < 0) - { - return drive; - } - - result = truename(name, PriPathName, FALSE); - if (result != SUCCESS) - { + result = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) return result; - } - current_ldt = &CDSp[drive]; - if (current_ldt->cdsFlags & CDSNETWDRV) - { + if (result & IS_NETWORK) return remote_setfattr(attrp); - } - else - { + + if (result & IS_DEVICE) + return DE_FILENOTFND; + /* /// Use truename()'s result, which we already have in PriPathName. I copy it to tmp_name because PriPathName is global and seems to get trashed somewhere in transit. @@ -1536,9 +1280,7 @@ COUNT DosSetFattr(BYTE FAR * name, UWORD attrp) see DosGetAttr() */ - return dos_setfattr(PriPathName, attrp); - - } + return dos_setfattr(PriPathName, attrp); } UBYTE DosSelectDrv(UBYTE drv) @@ -1558,137 +1300,90 @@ UBYTE DosSelectDrv(UBYTE drv) COUNT DosDelete(BYTE FAR * path, int attrib) { - COUNT result, drive; + COUNT result; - if (IsDevice(path)) - { - return DE_FILENOTFND; - } - - drive = get_verify_drive(path); - if (drive < 0) - { - return drive; - } - result = truename(path, PriPathName, FALSE); - if (result != SUCCESS) - { + result = truename(path, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) return result; - } - current_ldt = &CDSp[drive]; - if (current_ldt->cdsFlags & CDSNETWDRV) - { + + if (result & IS_NETWORK) return remote_delete(); - } - else - { - return dos_delete(PriPathName, attrib); - } + + if (result & IS_DEVICE) + return DE_FILENOTFND; + + return dos_delete(PriPathName, attrib); } COUNT DosRenameTrue(BYTE * path1, BYTE * path2, int attrib) { - COUNT drive1, drive2; - - if (IsDevice(path1) || IsDevice(path2)) - { - return DE_FILENOTFND; - } - - drive1 = get_verify_drive(path1); - drive2 = get_verify_drive(path2); - if ((drive1 != drive2) || (drive1 < 0)) + if (path1[0] != path2[0]) { return DE_INVLDDRV; } - current_ldt = &CDSp[drive1]; if (current_ldt->cdsFlags & CDSNETWDRV) - { return remote_rename(); - } - else - { - return dos_rename(PriPathName, SecPathName, attrib); - } + + return dos_rename(path1, path2, attrib); } COUNT DosRename(BYTE FAR * path1, BYTE FAR * path2) { COUNT result; - result = truename(path1, PriPathName, FALSE); - if (result != SUCCESS) - { + result = truename(path2, SecPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) return result; - } - result = truename(path2, SecPathName, FALSE); - if (result != SUCCESS) - { + if (!(result & IS_NETWORK) && (result & IS_DEVICE)) + return DE_FILENOTFND; + + result = truename(path1, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) return result; - } + + if (!(result & IS_NETWORK) && (result & IS_DEVICE)) + return DE_FILENOTFND; return DosRenameTrue(PriPathName, SecPathName, D_ALL); } -COUNT DosMkdir(BYTE FAR * dir) +COUNT DosMkdir(const char FAR * dir) { - COUNT result, drive; + COUNT result; - if (IsDevice(dir)) - { - return DE_PATHNOTFND; - } - - drive = get_verify_drive(dir); - if (drive < 0) - { - return drive; - } - result = truename(dir, PriPathName, FALSE); - if (result != SUCCESS) - { + result = truename(dir, PriPathName, CDS_MODE_CHECK_DEV_PATH); + if (result < SUCCESS) return result; - } - current_ldt = &CDSp[drive]; - if (current_ldt->cdsFlags & CDSNETWDRV) - { + + if (result & IS_NETWORK) return remote_mkdir(); - } - else - { - return dos_mkdir(PriPathName); - } + + if (result & IS_DEVICE) + return DE_ACCESS; + + return dos_mkdir(PriPathName); } -COUNT DosRmdir(BYTE FAR * dir) +/* This function is almost identical to DosMkdir(). + Maybe it would be nice to merge both functions. + -- 2001/09/03 ska*/ +COUNT DosRmdir(const char FAR * dir) { - COUNT result, drive; + COUNT result; - if (IsDevice(dir)) - { - return DE_PATHNOTFND; - } + result = truename(dir, PriPathName, CDS_MODE_CHECK_DEV_PATH); - drive = get_verify_drive(dir); - if (drive < 0) - { - return drive; - } - result = truename(dir, PriPathName, FALSE); - if (result != SUCCESS) - { + if (result < SUCCESS) return result; - } - current_ldt = &CDSp[drive]; - if (CDSp[drive].cdsFlags & CDSNETWDRV) - { + + if (result & IS_NETWORK) return remote_rmdir(); - } - else - { - return dos_rmdir(PriPathName); - } + + if (result & IS_DEVICE) + return DE_ACCESS; + + return dos_rmdir(PriPathName); } /* /// Added for SHARE. - Ron Cemer */ @@ -1698,7 +1393,7 @@ COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock) sft FAR *s; /* Get the SFT block that contains the SFT */ - if ((s = get_sft(hndl)) == (sft FAR *) - 1) + if (FP_OFF(s = get_sft(hndl)) == (size_t) - 1) return DE_INVLDHNDL; if (s->sft_flags & SFT_FSHARED) @@ -1723,10 +1418,10 @@ COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock) */ /* check for a device */ -struct dhdr FAR *IsDevice(BYTE FAR * fname) +struct dhdr FAR *IsDevice(const char FAR * fname) { struct dhdr FAR *dhp; - char FAR *froot = get_root(fname); + const char FAR *froot = get_root(fname); int i; /* /// BUG!!! This is absolutely wrong. A filename of "NUL.LST" must be @@ -1790,7 +1485,7 @@ BOOL IsShareInstalled(void) error. If < 0 is returned, it is the negated error return code, so DOS simply negates this value and returns it in AX. */ -STATIC int share_open_check(char far * filename, /* far pointer to fully qualified filename */ +STATIC int share_open_check(char * filename, /* pointer to fully qualified filename */ unsigned short pspseg, /* psp segment address of owner process */ int openmode, /* 0=read-only, 1=write-only, 2=read-write */ int sharemode) @@ -1894,6 +1589,18 @@ STATIC int remote_lock_unlock(sft FAR *sftp, /* SFT for file */ return ((regs.flags & 1) ? -(int)regs.a.b.l : 0); } +COUNT DosTruename(const char FAR *src, char FAR *dest) +{ + /* RBIL: The buffer has be unchanged, if the call fails. + Therefore, the name is created in an internal buffer + and copied into the user buffer only on success. + */ + COUNT rc = truename(src, PriPathName, 0); + if (rc >= SUCCESS) + fstrcpy(dest, PriPathName); + return rc; +} + /* * diff --git a/kernel/dosnames.c b/kernel/dosnames.c index 3a67d99..099d82d 100644 --- a/kernel/dosnames.c +++ b/kernel/dosnames.c @@ -41,9 +41,12 @@ const char _DirWildNameChars[] = "*?./\\\"[]:|<>+=;,"; #define PathSep(c) ((c)=='/'||(c)=='\\') #define DriveChar(c) (((c)>='A'&&(c)<='Z')||((c)>='a'&&(c)<='z')) -#define DirChar(c) (!strchr(_DirWildNameChars+5, (c))) -#define WildChar(c) (!strchr(_DirWildNameChars+2, (c))) -#define NameChar(c) (!strchr(_DirWildNameChars, (c))) +#define DirChar(c) (((unsigned char)(c)) >= ' ' && \ + !strchr(_DirWildNameChars+5, (c))) +#define WildChar(c) (((unsigned char)(c)) >= ' ' && \ + !strchr(_DirWildNameChars+2, (c))) +#define NameChar(c) (((unsigned char)(c)) >= ' ' && \ + !strchr(_DirWildNameChars, (c))) VOID XlateLcase(BYTE * szFname, COUNT nChars); VOID DosTrimPath(BYTE * lpszPathNamep); @@ -61,14 +64,6 @@ VOID XlateLcase(BYTE * szFname, COUNT nChars) } #endif -VOID SpacePad(BYTE * szString, COUNT nChars) -{ - REG COUNT i; - - for (i = strlen(szString); i < nChars; i++) - szString[i] = ' '; -} - /* MSD durring an FindFirst search string looks like this; (*), & (.) == Current directory *.* @@ -76,90 +71,73 @@ VOID SpacePad(BYTE * szString, COUNT nChars) (..) == Back one directory *.* This always has a "truename" as input, so we may do some shortcuts + + returns number of characters in the directory component (up to the + last backslash, including d:) or negative if error */ -COUNT ParseDosName(BYTE * lpszFileName, - COUNT * pnDrive, - BYTE * pszDir, - BYTE * pszFile, BYTE * pszExt, BOOL bAllowWildcards) +int ParseDosName(const char *filename, char *fcbname, BOOL bAllowWildcards) { - COUNT nDirCnt, nFileCnt, nExtCnt; - BYTE *lpszLclDir, *lpszLclFile, *lpszLclExt; + int nDirCnt, nFileCnt, nExtCnt; + const char *lpszLclDir, *lpszLclFile, *lpszLclExt; /* Initialize the users data fields */ - if (pszDir) - *pszDir = '\0'; - if (pszFile) - *pszFile = '\0'; - if (pszExt) - *pszExt = '\0'; - lpszLclFile = lpszLclExt = lpszLclDir = 0; nDirCnt = nFileCnt = nExtCnt = 0; - /* found a drive, fetch it and bump pointer past drive */ /* NB: this code assumes ASCII */ - if (pnDrive) - *pnDrive = *lpszFileName - 'A'; - lpszFileName += 2; - if (!pszDir && !pszFile && !pszExt) - return SUCCESS; /* Now see how long a directory component we have. */ - lpszLclDir = lpszLclFile = lpszFileName; - while (DirChar(*lpszFileName)) + lpszLclDir = lpszLclFile = filename; + filename += 2; + + while (DirChar(*filename)) { - if (*lpszFileName == '\\') - lpszLclFile = lpszFileName + 1; - ++lpszFileName; + if (*filename == '\\') + lpszLclFile = filename + 1; + ++filename; } - nDirCnt = FP_OFF(lpszLclFile) - FP_OFF(lpszLclDir); + nDirCnt = lpszLclFile - lpszLclDir; /* Fix lengths to maximums allowed by MS-DOS. */ if (nDirCnt > PARSE_MAX - 1) nDirCnt = PARSE_MAX - 1; /* Parse out the file name portion. */ - lpszFileName = lpszLclFile; - while (bAllowWildcards ? WildChar(*lpszFileName) : - NameChar(*lpszFileName)) + filename = lpszLclFile; + while (bAllowWildcards ? WildChar(*filename) : + NameChar(*filename)) { ++nFileCnt; - ++lpszFileName; + ++filename; } if (nFileCnt == 0) + { /* Lixing Yuan Patch */ if (bAllowWildcards) /* for find first */ { - if (*lpszFileName != '\0') + if (*filename != '\0') return DE_FILENOTFND; if (nDirCnt == 1) /* for d:\ */ return DE_NFILES; - if (pszDir) - { - memcpy(pszDir, lpszLclDir, nDirCnt); - pszDir[nDirCnt] = '\0'; - } - if (pszFile) - memcpy(pszFile, "????????", FNAME_SIZE + 1); - if (pszExt) - memcpy(pszExt, "???", FEXT_SIZE + 1); - return SUCCESS; + memset(fcbname, '?', FNAME_SIZE + FEXT_SIZE); + return nDirCnt; } else return DE_FILENOTFND; - + } + /* Now we have pointers set to the directory portion and the */ /* file portion. Now determine the existance of an extension. */ - lpszLclExt = lpszFileName; - if ('.' == *lpszFileName) + lpszLclExt = filename; + if ('.' == *filename) { - lpszLclExt = ++lpszFileName; - while (*lpszFileName) + lpszLclExt = ++filename; + while (*filename) { - if (bAllowWildcards ? WildChar(*lpszFileName) : - NameChar(*lpszFileName)) + if (bAllowWildcards ? WildChar(*filename) : + NameChar(*filename)) { ++nExtCnt; - ++lpszFileName; + ++filename; } else { @@ -167,225 +145,20 @@ COUNT ParseDosName(BYTE * lpszFileName, } } } - else if (*lpszFileName) + else if (*filename) return DE_FILENOTFND; /* Finally copy whatever the user wants extracted to the user's */ /* buffers. */ - if (pszDir) - { - memcpy(pszDir, lpszLclDir, nDirCnt); - pszDir[nDirCnt] = '\0'; - } - if (pszFile) - { - memcpy(pszFile, lpszLclFile, nFileCnt); - pszFile[nFileCnt] = '\0'; - } - if (pszExt) - { - memcpy(pszExt, lpszLclExt, nExtCnt); - pszExt[nExtCnt] = '\0'; - } + memset(fcbname, ' ', FNAME_SIZE + FEXT_SIZE); + memcpy(fcbname, lpszLclFile, nFileCnt); + memcpy(&fcbname[FNAME_SIZE], lpszLclExt, nExtCnt); /* Clean up before leaving */ - return SUCCESS; + return nDirCnt; } -#if 0 -/* not necessary anymore because of truename */ -COUNT ParseDosPath(BYTE * lpszFileName, - COUNT * pnDrive, BYTE * pszDir, BYTE * pszCurPath) -{ - COUNT nDirCnt, nPathCnt; - BYTE *lpszLclDir, *pszBase = pszDir; - - /* Initialize the users data fields */ - *pszDir = '\0'; - lpszLclDir = 0; - nDirCnt = nPathCnt = 0; - - /* Start by cheking for a drive specifier ... */ - if (DriveChar(*lpszFileName) && ':' == lpszFileName[1]) - { - /* found a drive, fetch it and bump pointer past drive */ - /* NB: this code assumes ASCII */ - if (pnDrive) - { - *pnDrive = *lpszFileName - 'A'; - if (*pnDrive > 26) - *pnDrive -= ('a' - 'A'); - } - lpszFileName += 2; - } - else - { - if (pnDrive) - { - *pnDrive = -1; - } - } - - lpszLclDir = lpszFileName; - if (!PathSep(*lpszLclDir)) - { - fstrncpy(pszDir, pszCurPath, PARSE_MAX - 1); - /*TE*/ nPathCnt = fstrlen(pszCurPath); - if (!PathSep(pszDir[nPathCnt - 1]) && nPathCnt < PARSE_MAX - 1) - /*TE*/ pszDir[nPathCnt++] = '\\'; - if (nPathCnt > PARSE_MAX) - nPathCnt = PARSE_MAX; - pszDir += nPathCnt; - } - - /* Now see how long a directory component we have. */ - while (NameChar(*lpszFileName) - || PathSep(*lpszFileName) || '.' == *lpszFileName) - { - ++nDirCnt; - ++lpszFileName; - } - - /* Fix lengths to maximums allowed by MS-DOS. */ - if ((nDirCnt + nPathCnt) > PARSE_MAX - 1) - /*TE*/ nDirCnt = PARSE_MAX - 1 - nPathCnt; - - /* Finally copy whatever the user wants extracted to the user's */ - /* buffers. */ - if (pszDir) - { - memcpy(pszDir, lpszLclDir, nDirCnt); - pszDir[nDirCnt] = '\0'; - } - - /* Clean up before leaving */ - DosTrimPath(pszBase); - - /* Before returning to the user, eliminate any useless */ - /* trailing "\\." since the path prior to this is sufficient. */ - nPathCnt = strlen(pszBase); - if (2 == nPathCnt) /* Special case, root */ - { - if (!strcmp(pszBase, "\\.")) - pszBase[1] = '\0'; - } - else if (2 < nPathCnt) - { - if (!strcmp(&pszBase[nPathCnt - 2], "\\.")) - pszBase[nPathCnt - 2] = '\0'; - } - - return SUCCESS; -} - -VOID DosTrimPath(BYTE * lpszPathNamep) -{ - BYTE *lpszLast, *lpszNext, *lpszRoot = NULL; - COUNT nChars, flDotDot; - - /* First, convert all '/' to '\'. Look for root as we scan */ - if (*lpszPathNamep == '\\') - lpszRoot = lpszPathNamep; - for (lpszNext = lpszPathNamep; *lpszNext; ++lpszNext) - { - if (*lpszNext == '/') - *lpszNext = '\\'; - if (!lpszRoot && *lpszNext == ':' && *(lpszNext + 1) == '\\') - lpszRoot = lpszNext + 1; - } - - /* NAMEMAX + 2, must include C: TE */ - for (lpszLast = lpszNext = lpszPathNamep, nChars = 0; - *lpszNext != '\0' && nChars < NAMEMAX + 2;) - { - /* Initialize flag for loop. */ - flDotDot = FALSE; - - /* If we are at a path seperator, check for extra path */ - /* seperator, '.' and '..' to reduce. */ - if (*lpszNext == '\\') - { - /* If it's '\', just move everything down one. */ - if (*(lpszNext + 1) == '\\') - fstrncpy(lpszNext, lpszNext + 1, NAMEMAX); - /* also check for '.' and '..' and move down */ - /* as appropriate. */ - else if (*(lpszNext + 1) == '.') - { - if (*(lpszNext + 2) == '.' && !(*(lpszNext + 3))) - { - /* At the end, just truncate */ - /* and exit. */ - if (lpszLast == lpszRoot) - *(lpszLast + 1) = '\0'; - else - *lpszLast = '\0'; - return; - } - - if (*(lpszNext + 2) == '.' && *(lpszNext + 3) == '\\') - { - fstrncpy(lpszLast, lpszNext + 3, NAMEMAX); - /* bump back to the last */ - /* seperator. */ - lpszNext = lpszLast; - /* set lpszLast to the last one */ - if (lpszLast <= lpszPathNamep) - continue; - do - { - --lpszLast; - } - while (lpszLast != lpszPathNamep && *lpszLast != '\\'); - flDotDot = TRUE; - } - /* Note: we skip strange stuff that */ - /* starts with '.' */ - else if (*(lpszNext + 2) == '\\') - { - fstrncpy(lpszNext, lpszNext + 2, NAMEMAX); - flDotDot = TRUE; - } - /* If we're at the end of a string, */ - /* just exit. */ - else if (*(lpszNext + 2) == NULL) - { - return; - } - /* - Added this "else" because otherwise we might not pass - any of the foregoing tests, as in the case where the - incoming string refers to a suffix only, like ".bat" - - -SRM - */ - else - { - lpszLast = lpszNext++; - } - } - else - { - /* No '.' or '\' so mark it and bump */ - /* past */ - lpszLast = lpszNext++; - continue; - } - - /* Done. Now set last to next to mark this */ - /* instance of path seperator. */ - if (!flDotDot) - lpszLast = lpszNext; - } - else - /* For all other cases, bump lpszNext for the */ - /* next check */ - ++lpszNext; - } -} -#endif - /* * Log: dosnames.c,v - for newer log entries do "cvs log dosnames.c" * diff --git a/kernel/entry.asm b/kernel/entry.asm index 059637e..2424368 100644 --- a/kernel/entry.asm +++ b/kernel/entry.asm @@ -376,7 +376,11 @@ int21_exit_nodec: pop si %IFDEF I386 - sub bp,8 +%ifdef WATCOM + sub bp, 4 ; for fs and gs only +%else + sub bp, 8 ; high parts of eax, ebx, ecx, edx +%endif %endif cli diff --git a/kernel/fatdir.c b/kernel/fatdir.c index a95897b..25ca4ef 100644 --- a/kernel/fatdir.c +++ b/kernel/fatdir.c @@ -68,14 +68,10 @@ VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart) fnp->f_cluster = fnp->f_dirstart = dirstart; } -f_node_ptr dir_open(BYTE * dirname) +f_node_ptr dir_open(register const char *dirname) { f_node_ptr fnp; - COUNT drive; - BYTE *p; - WORD i; - struct cds FAR *cdsp; - BYTE *pszPath = dirname + 2; + int i; /* Allocate an fnode if possible - error return (0) if not. */ if ((fnp = get_f_node()) == (f_node_ptr) 0) @@ -86,57 +82,23 @@ f_node_ptr dir_open(BYTE * dirname) /* Force the fnode into read-write mode */ fnp->f_mode = RDWR; - /* determine what drive we are using... */ - if (ParseDosName - (dirname, &drive, (BYTE *) 0, (BYTE *) 0, (BYTE *) 0, - FALSE) != SUCCESS) + /* determine what drive and dpb we are using... */ + fnp->f_dpb = CDSp[dirname[0]-'A'].cdsDpb; + if (fnp->f_dpb == 0) { release_f_node(fnp); return NULL; } - /* If the drive was specified, drive is non-negative and */ - /* corresponds to the one passed in, i.e., 0 = A, 1 = B, etc. */ - /* We use that and skip the "D:" part of the string. */ - /* Otherwise, just use the default drive */ - if (drive >= 0) - { - dirname += 2; /* Assume FAT style drive */ - } - else - { - drive = default_drive; - } - if (drive >= lastdrive) - { - release_f_node(fnp); - return NULL; - } - - cdsp = &CDSp[drive]; - - /* Generate full path name */ - /* not necessary anymore, since truename did that already - i = cdsp->cdsJoinOffset; - ParseDosPath(dirname, (COUNT *) 0, pszPath, (BYTE FAR *) & cdsp->cdsCurrentPath[i]); */ - /* for testing only for now */ #if 0 - if ((cdsp->cdsFlags & CDSNETWDRV)) + if ((CDSp[dirname[0]-'A'].cdsFlags & CDSNETWDRV)) { printf("FailSafe %x \n", Int21AX); return fnp; } #endif - if (cdsp->cdsDpb == 0) - { - release_f_node(fnp); - return NULL; - } - - fnp->f_dpb = cdsp->cdsDpb; - /* Perform all directory common handling after all special */ /* handling has been performed. */ @@ -150,15 +112,21 @@ f_node_ptr dir_open(BYTE * dirname) /* */ /* Start from the root directory (dirstart = 0) */ + /* The CDS's cdsStartCls may be used to shorten the search + beginning at the CWD, see mapPath() and CDS.H in order + to enable this behaviour there. + -- 2001/09/04 ska*/ + dir_init_fnode(fnp, 0); - for (p = pszPath; *p != '\0';) + dirname += 2; /* Assume FAT style drive */ + while(*dirname != '\0') { /* skip all path seperators */ - while (*p == '\\') - ++p; + while (*dirname == '\\') + ++dirname; /* don't continue if we're at the end */ - if (*p == '\0') + if (*dirname == '\0') break; /* Convert the name into an absolute name for */ @@ -169,20 +137,22 @@ f_node_ptr dir_open(BYTE * dirname) for (i = 0; i < FNAME_SIZE; i++) { - if (*p != '\0' && *p != '.' && *p != '/' && *p != '\\') - TempBuffer[i] = *p++; + if (*dirname != '\0' && *dirname != '.' && *dirname != '/' && + *dirname != '\\') + TempBuffer[i] = *dirname++; else break; } /* and the extension (don't forget to */ /* add trailing spaces)... */ - if (*p == '.') - ++p; + if (*dirname == '.') + ++dirname; for (i = 0; i < FEXT_SIZE; i++) { - if (*p != '\0' && *p != '.' && *p != '/' && *p != '\\') - TempBuffer[i + FNAME_SIZE] = *p++; + if (*dirname != '\0' && *dirname != '.' && *dirname != '/' && + *dirname != '\\') + TempBuffer[i + FNAME_SIZE] = *dirname++; else break; } @@ -191,27 +161,18 @@ f_node_ptr dir_open(BYTE * dirname) /* find the entry... */ i = FALSE; - DosUpFMem((BYTE FAR *) TempBuffer, FNAME_SIZE + FEXT_SIZE); - while (dir_read(fnp) == 1) { - if (fnp->f_dir.dir_name[0] != '\0' - && fnp->f_dir.dir_name[0] != DELETED - && !(fnp->f_dir.dir_attrib & D_VOLID)) + if (!(fnp->f_dir.dir_attrib & D_VOLID) && + fcbmatch(TempBuffer, fnp->f_dir.dir_name)) { - if (fcmp - (TempBuffer, (BYTE *) fnp->f_dir.dir_name, - FNAME_SIZE + FEXT_SIZE)) - { - i = TRUE; - break; - } + i = TRUE; + break; } } if (!i || !(fnp->f_dir.dir_attrib & D_DIR)) { - release_f_node(fnp); return (f_node_ptr) 0; } @@ -225,6 +186,15 @@ f_node_ptr dir_open(BYTE * dirname) return fnp; } +/* swap internal and external delete flags */ +STATIC void swap_deleted(char *name) +{ + if (name[0] == DELETED) + name[0] = EXT_DELETED; + else if (name[0] == EXT_DELETED) + name[0] = DELETED; +} + /* Description. * Read next consequitive directory entry, pointed by fnp. * If some error occures the other critical @@ -306,6 +276,8 @@ COUNT dir_read(REG f_node_ptr fnp) b_buffer[((UWORD) new_diroff) % fnp->f_dpb->dpb_secsize], (struct dirent FAR *)&fnp->f_dir); + swap_deleted(fnp->f_dir.dir_name); + /* Update the fnode's directory info */ fnp->f_flags.f_dmod = FALSE; fnp->f_flags.f_dnew = FALSE; @@ -399,10 +371,15 @@ BOOL dir_write(REG f_node_ptr fnp) if (fnp->f_flags.f_dnew && fnp->f_dir.dir_attrib != D_LFN) fmemset(&fnp->f_dir.dir_case, 0, 8); + + swap_deleted(fnp->f_dir.dir_name); + putdirent((struct dirent FAR *)&fnp->f_dir, (VOID FAR *) & bp->b_buffer[(UWORD) fnp->f_diroff % fnp->f_dpb->dpb_secsize]); + swap_deleted(fnp->f_dir.dir_name); + bp->b_flag &= ~(BFR_DATA | BFR_FAT); bp->b_flag |= BFR_DIR | BFR_DIRTY | BFR_VALID; } @@ -422,6 +399,7 @@ VOID dir_close(REG f_node_ptr fnp) #endif /* Clear buffers after release */ + /* hazard: no error checking! */ flush_buffers(fnp->f_dpb->dpb_unit); /* and release this instance of the fnode */ @@ -434,10 +412,6 @@ COUNT dos_findfirst(UCOUNT attr, BYTE * name) REG f_node_ptr fnp; REG dmatch *dmp = (dmatch *) TempBuffer; REG COUNT i; - COUNT nDrive; - BYTE *p; - - BYTE local_name[FNAME_SIZE + 1], local_ext[FEXT_SIZE + 1]; /* printf("ff %Fs\n", name);*/ @@ -449,63 +423,37 @@ COUNT dos_findfirst(UCOUNT attr, BYTE * name) /* current directory, do a seek and read, then close the fnode. */ /* Parse out the drive, file name and file extension. */ - i = ParseDosName(name, &nDrive, &szDirName[2], local_name, local_ext, - TRUE); - if (i != SUCCESS) + i = ParseDosName(name, SearchDir.dir_name, TRUE); + if (i < SUCCESS) return i; /* printf("\nff %s", Tname); - printf("ff %s", local_name); - printf("ff %s\n", local_ext); + printf("ff %s", fcbname); */ - /* Build the match pattern out of the passed string */ - /* copy the part of the pattern which belongs to the filename and is fixed */ - for (p = local_name, i = 0; i < FNAME_SIZE && *p; ++p, ++i) - SearchDir.dir_name[i] = *p; - - for (; i < FNAME_SIZE; ++i) - SearchDir.dir_name[i] = ' '; - - /* and the extension (don't forget to add trailing spaces)... */ - for (p = local_ext, i = 0; i < FEXT_SIZE && *p; ++p, ++i) - SearchDir.dir_ext[i] = *p; - - for (; i < FEXT_SIZE; ++i) - SearchDir.dir_ext[i] = ' '; - - /* Convert everything to uppercase. */ - DosUpFMem(SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); - /* Now search through the directory to find the entry... */ - /* Complete building the directory from the passed in */ - /* name */ - szDirName[0] = 'A' + nDrive; - szDirName[1] = ':'; - /* Special handling - the volume id is only in the root */ /* directory and only searched for once. So we need to open */ /* the root and return only the first entry that contains the */ /* volume id bit set. */ if (attr == D_VOLID) - { - szDirName[2] = '\\'; - szDirName[3] = '\0'; - } + i = 3; /* Now open this directory so that we can read the */ /* fnode entry and do a match on it. */ /* printf("dir_open %s\n", szDirName);*/ - if ((fnp = dir_open(szDirName)) == NULL) - return DE_PATHNOTFND; + { + char tmp = name[i]; + name[i] = '\0'; + if ((fnp = dir_open(name)) == NULL) + return DE_PATHNOTFND; + name[i] = tmp; + } /* Now initialize the dirmatch structure. */ - nDrive = get_verify_drive(name); - if (nDrive < 0) - return nDrive; - dmp->dm_drive = nDrive; + dmp->dm_drive = name[0] - 'A'; dmp->dm_attr_srch = attr; /* Copy the raw pattern from our data segment to the DTA. */ @@ -605,9 +553,7 @@ COUNT dos_findnext(void) if (fnp->f_dir.dir_name[0] != '\0' && fnp->f_dir.dir_name[0] != DELETED && (fnp->f_dir.dir_attrib & D_VOLID) != D_VOLID) { - if (fcmp_wild - ((BYTE FAR *) dmp->dm_name_pat, (BYTE FAR *) fnp->f_dir.dir_name, - FNAME_SIZE + FEXT_SIZE)) + if (fcmp_wild(dmp->dm_name_pat, fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE)) { /* MSD Command.com uses FCB FN 11 & 12 with attrib set to 0x16. @@ -694,6 +640,7 @@ void ConvertName83ToNameSZ(BYTE FAR * destSZ, BYTE FAR * srcFCBName) *destSZ = '\0'; } +#if 0 /* returns the asciiSZ length of a 8.3 filename */ @@ -706,6 +653,7 @@ int FileName83Length(BYTE * filename83) return strlen(buff); } +#endif /* * Log: fatdir.c,v - for newer log entries do a "cvs log fatdir.c" diff --git a/kernel/fatfs.c b/kernel/fatfs.c index 6c2db6c..d733bc5 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -39,8 +39,8 @@ BYTE *RcsId = "$Id$"; /* */ f_node_ptr xlt_fd(COUNT); COUNT xlt_fnp(f_node_ptr); -f_node_ptr split_path(BYTE *, BYTE *, BYTE *); -BOOL find_fname(f_node_ptr, BYTE *, BYTE *, int); +STATIC f_node_ptr split_path(char *, char *); +BOOL find_fname(f_node_ptr, char *, int); /* /// Added - Ron Cemer */ STATIC void merge_file_changes(f_node_ptr fnp, int collect); /* /// Added - Ron Cemer */ @@ -77,63 +77,158 @@ ULONG clus2phys(CLUSTER cl_no, struct dpb FAR * dpbp) /* Open a file given the path. Flags is 0 for read, 1 for write and 2 */ /* for update. */ -/* Returns an integer file desriptor or a negative error code */ +/* Returns an long where the high word is a status code and the low */ +/* word is an integer file descriptor or a negative error code */ +/* see DosOpenSft(), dosfns.c for an explanation of the flags bits */ +/* directory opens are allowed here; these are not allowed by DosOpenSft*/ -COUNT dos_open(BYTE * path, COUNT flag) +long dos_open(char *path, unsigned flags, unsigned attrib) { REG f_node_ptr fnp; + char fcbname[FNAME_SIZE + FEXT_SIZE]; + int status = S_OPENED; - /* First test the flag to see if the user has passed a valid */ + /* First test the flags to see if the user has passed a valid */ /* file mode... */ - if (flag < 0 || flag > 2) + if ((flags & 3) > 2) return DE_INVLDACC; /* first split the passed dir into comopnents (i.e. - path to */ /* new directory and name of new directory. */ - if ((fnp = split_path(path, szFileName, szFileExt)) == NULL) - { + if ((fnp = split_path(path, fcbname)) == NULL) return DE_PATHNOTFND; - } - /* Look for the file. If we can't find it, just return a not */ - /* found error. */ - if (!find_fname(fnp, szFileName, szFileExt, D_ALL)) + /* Check that we don't have a duplicate name, so if we */ + /* find one, truncate it (O_CREAT). */ + if (find_fname(fnp, fcbname, D_ALL | attrib)) { + if (flags & O_TRUNC) + { + /* The only permissable attribute is archive, */ + /* check for any other bit set. If it is, give */ + /* an access error. */ + if ((fnp->f_dir.dir_attrib & (D_RDONLY | D_DIR | D_VOLID)) + || (fnp->f_dir.dir_attrib & ~D_ARCHIVE & ~attrib)) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Release the existing files FAT and set the */ + /* length to zero, effectively truncating the */ + /* file to zero. */ + wipe_out(fnp); + status = S_REPLACED; + } + else if (!(flags & O_OPEN)) + { + dir_close(fnp); + return DE_FILEEXISTS; + } + } + else if (flags & O_CREAT) + { + BOOL is_free; + + /* Reset the directory by a close followed by */ + /* an open */ + fnp->f_flags.f_dmod = FALSE; + dir_close(fnp); + fnp = split_path(path, fcbname); + + /* Get a free f_node pointer so that we can use */ + /* it in building the new file. */ + /* Note that if we're in the root and we don't */ + /* find an empty slot, we need to abort. */ + if (((is_free = find_free(fnp)) == 0) && (fnp->f_flags.f_droot)) + { + fnp->f_flags.f_dmod = FALSE; + dir_close(fnp); + return DE_TOOMANY; + } + + /* Otherwise just expand the directory */ + else if (!is_free && !(fnp->f_flags.f_droot)) + { + COUNT ret; + + if ((ret = extend_dir(fnp)) != SUCCESS) + /* fnp already closed in extend_dir */ + return ret; + } + + /* put the fnode's name into the directory. */ + memcpy(fnp->f_dir.dir_name, fcbname, FNAME_SIZE + FEXT_SIZE); + status = S_CREATED; + } + else + { + /* open: If we can't find the file, just return a not */ + /* found error. */ dir_close(fnp); return DE_FILENOTFND; } + + /* Set the fnode to the desired mode */ + /* Updating the directory entry first. */ + fnp->f_mode = flags & 3; + + if (status != S_OPENED) + { + fnp->f_dir.dir_size = 0l; + setdstart(fnp->f_dir, FREE); + fnp->f_dir.dir_attrib = attrib; + fnp->f_dir.dir_time = dos_gettime(); + fnp->f_dir.dir_date = dos_getdate(); + + fnp->f_flags.f_dmod = TRUE; + fnp->f_flags.f_ddate = FALSE; + fnp->f_flags.f_dnew = FALSE; + fnp->f_flags.f_ddir = TRUE; + if (!dir_write(fnp)) + { + release_f_node(fnp); + return DE_ACCESS; + } + } - /* Set the fnode to the desired mode */ - fnp->f_mode = flag; + /* force r/o open for FCBs if the file is read-only */ + if ((flags & O_FCB) && (fnp->f_dir.dir_attrib & D_RDONLY)) + fnp->f_mode = O_RDONLY; - /* Initialize the rest of the fnode. */ + /* Check permissions. -- JPP */ + if ((fnp->f_dir.dir_attrib & D_RDONLY) && (fnp->f_mode != O_RDONLY)) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Now change to file */ fnp->f_offset = 0l; fnp->f_highwater = fnp->f_dir.dir_size; - + fnp->f_back = LONG_LAST_CLUSTER; - - fnp->f_flags.f_dmod = FALSE; + if (status != S_OPENED) + { + fnp->f_cluster = FREE; + setdstart(fnp->f_dir, FREE); + fnp->f_cluster_offset = 0l; /*JPP */ + } + + fnp->f_flags.f_dmod = (status != S_OPENED); + fnp->f_flags.f_ddate = FALSE; fnp->f_flags.f_dnew = FALSE; fnp->f_flags.f_ddir = FALSE; - - merge_file_changes(fnp, TRUE); /* /// Added - Ron Cemer */ - + + merge_file_changes(fnp, status == S_OPENED); /* /// Added - Ron Cemer */ /* /// Moved from above. - Ron Cemer */ fnp->f_cluster = getdstart(fnp->f_dir); fnp->f_cluster_offset = 0l; /*JPP */ - return xlt_fnp(fnp); + return xlt_fnp(fnp) | ((long)status << 16); } -BOOL fcmp(BYTE * s1, BYTE * s2, COUNT n) -{ - while (n--) - if (*s1++ != *s2++) - return FALSE; - return TRUE; -} - -BOOL fcmp_wild(BYTE FAR * s1, BYTE FAR * s2, COUNT n) +BOOL fcmp_wild(const char * s1, const char * s2, unsigned n) { while (n--) { @@ -203,31 +298,15 @@ COUNT dos_commit(COUNT fd) /* */ /* split a path into it's component directory and file name */ /* */ -f_node_ptr split_path(BYTE * path, BYTE * fname, BYTE * fext) +f_node_ptr split_path(char * path, char * fcbname) { REG f_node_ptr fnp; - COUNT nDrive; - struct cds FAR *cdsp; - /* Start off by parsing out the components. */ - if (ParseDosName(path, &nDrive, &szDirName[2], fname, fext, FALSE) - != SUCCESS) + /* Start off by parsing out the components. */ + int dirlength = ParseDosName(path, fcbname, FALSE); + + if (dirlength < SUCCESS) return (f_node_ptr) 0; - if (nDrive < 0) - nDrive = default_drive; - - szDirName[0] = 'A' + nDrive; - szDirName[1] = ':'; - - /* Add trailing spaces to the file name and extension */ - SpacePad(fname, FNAME_SIZE); - SpacePad(fext, FEXT_SIZE); - - if (nDrive >= lastdrive) - { - return (f_node_ptr) 0; - } - cdsp = &CDSp[nDrive]; /* 11/29/99 jt * Networking and Cdroms. You can put in here a return. @@ -241,7 +320,7 @@ f_node_ptr split_path(BYTE * path, BYTE * fname, BYTE * fext) */ #ifdef DEBUG - if (cdsp->cdsFlags & CDSNETWDRV) + if (CDSp[path[0]-'A'].cdsFlags & CDSNETWDRV) { printf("split path called for redirected file: `%s.%s'\n", fname, fext); @@ -250,7 +329,12 @@ f_node_ptr split_path(BYTE * path, BYTE * fname, BYTE * fext) #endif /* Translate the path into a useful pointer */ - fnp = dir_open(szDirName); + { + char tmp = path[dirlength]; + path[dirlength] = '\0'; + fnp = dir_open(path); + path[dirlength] = tmp; + } /* If the fd was invalid because it was out of range or the */ /* requested file was not open, tell the caller and exit... */ @@ -261,21 +345,32 @@ f_node_ptr split_path(BYTE * path, BYTE * fname, BYTE * fext) return (f_node_ptr) 0; } - /* Convert the name into an absolute name for comparison... */ - DosUpFString((BYTE FAR *) szDirName); - DosUpFMem((BYTE FAR *) fname, FNAME_SIZE); - DosUpFMem((BYTE FAR *) fext, FEXT_SIZE); - return fnp; } -STATIC BOOL find_fname(f_node_ptr fnp, BYTE * fname, BYTE * fext, int attr) +/* checks whether directory part of path exists */ +BOOL dir_exists(char * path) +{ + REG f_node_ptr fnp; + char fcbname[FNAME_SIZE + FEXT_SIZE]; + + if ((fnp = split_path(path, fcbname)) == NULL) + return FALSE; + + dir_close(fnp); + return TRUE; +} + +BOOL fcbmatch(const char *fcbname1, const char *fcbname2) +{ + return memcmp(fcbname1, fcbname2, FNAME_SIZE + FEXT_SIZE) == 0; +} + +STATIC BOOL find_fname(f_node_ptr fnp, char *fcbname, int attr) { while (dir_read(fnp) == 1) { - if (fnp->f_dir.dir_name[0] != DELETED - && fcmp(fname, (BYTE *) fnp->f_dir.dir_name, FNAME_SIZE) - && fcmp(fext, (BYTE *) fnp->f_dir.dir_ext, FEXT_SIZE) + if (fcbmatch(fnp->f_dir.dir_name, fcbname) && (fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE | attr)) == 0) { return TRUE; @@ -375,12 +470,7 @@ STATIC int is_same_file(f_node_ptr fnp1, f_node_ptr fnp2) return (fnp1->f_dpb->dpb_unit == fnp2->f_dpb->dpb_unit) && (fnp1->f_dpb->dpb_subunit == fnp2->f_dpb->dpb_subunit) - && (fcmp - ((BYTE *) fnp1->f_dir.dir_name, - (BYTE *) fnp2->f_dir.dir_name, FNAME_SIZE)) - && (fcmp - ((BYTE *) fnp1->f_dir.dir_ext, - (BYTE *) fnp2->f_dir.dir_ext, FEXT_SIZE)) + && (fcbmatch(fnp1->f_dir.dir_name, fnp2->f_dir.dir_name)) && ((fnp1->f_dir.dir_attrib & D_VOLID) == 0) && ((fnp2->f_dir.dir_attrib & D_VOLID) == 0) && (fnp1->f_diroff == fnp2->f_diroff) @@ -401,108 +491,6 @@ STATIC void copy_file_changes(f_node_ptr src, f_node_ptr dst) dst->f_dir.dir_time = src->f_dir.dir_time; } -COUNT dos_creat(BYTE * path, int attrib) -{ - REG f_node_ptr fnp; - - /* first split the passed dir into components (i.e. - */ - /* path to new directory and name of new directory */ - if ((fnp = split_path(path, szFileName, szFileExt)) == NULL) - { - return DE_PATHNOTFND; - } - - /* Check that we don't have a duplicate name, so if we */ - /* find one, truncate it. */ - if (find_fname(fnp, szFileName, szFileExt, D_ALL | attrib)) - { - /* The only permissable attribute is archive, */ - /* check for any other bit set. If it is, give */ - /* an access error. */ - if ((fnp->f_dir.dir_attrib & (D_RDONLY | D_DIR | D_VOLID)) - || (fnp->f_dir.dir_attrib & ~D_ARCHIVE & ~attrib)) - { - dir_close(fnp); - return DE_ACCESS; - } - - /* Release the existing files FAT and set the */ - /* length to zero, effectively truncating the */ - /* file to zero. */ - wipe_out(fnp); - } - else - { - BOOL is_free; - - /* Reset the directory by a close followed by */ - /* an open */ - fnp->f_flags.f_dmod = FALSE; - dir_close(fnp); - fnp = split_path(path, szFileName, szFileExt); - - /* Get a free f_node pointer so that we can use */ - /* it in building the new file. */ - /* Note that if we're in the root and we don't */ - /* find an empty slot, we need to abort. */ - if (((is_free = find_free(fnp)) == 0) && (fnp->f_flags.f_droot)) - { - fnp->f_flags.f_dmod = FALSE; - dir_close(fnp); - return DE_TOOMANY; - } - - /* Otherwise just expand the directory */ - else if (!is_free && !(fnp->f_flags.f_droot)) - { - COUNT ret; - - if ((ret = extend_dir(fnp)) != SUCCESS) - return ret; - } - - /* put the fnode's name into the directory. */ - memcpy(fnp->f_dir.dir_name, szFileName, FNAME_SIZE); - memcpy(fnp->f_dir.dir_ext, szFileExt, FEXT_SIZE); - } - /* Set the fnode to the desired mode */ - /* Updating the directory entry first. */ - fnp->f_mode = RDWR; - - fnp->f_dir.dir_size = 0l; - setdstart(fnp->f_dir, FREE); - fnp->f_dir.dir_attrib = attrib | D_ARCHIVE; - fnp->f_dir.dir_time = dos_gettime(); - fnp->f_dir.dir_date = dos_getdate(); - - fnp->f_flags.f_dmod = TRUE; - fnp->f_flags.f_ddate = FALSE; - fnp->f_flags.f_dnew = FALSE; - fnp->f_flags.f_ddir = TRUE; - if (!dir_write(fnp)) - { - release_f_node(fnp); - return DE_ACCESS; - } - - /* Now change to file */ - fnp->f_offset = 0l; - fnp->f_highwater = 0l; - - fnp->f_back = LONG_LAST_CLUSTER; - fnp->f_cluster = FREE; - setdstart(fnp->f_dir, FREE); - fnp->f_cluster_offset = 0l; /*JPP */ - fnp->f_flags.f_dmod = TRUE; - fnp->f_flags.f_ddate = FALSE; - fnp->f_flags.f_dnew = FALSE; - fnp->f_flags.f_ddir = FALSE; - - merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ - - return xlt_fnp(fnp); -} - STATIC COUNT delete_dir_entry(f_node_ptr fnp) { COUNT rc; @@ -529,17 +517,18 @@ STATIC COUNT delete_dir_entry(f_node_ptr fnp) COUNT dos_delete(BYTE * path, int attrib) { REG f_node_ptr fnp; + char fcbname[FNAME_SIZE + FEXT_SIZE]; /* first split the passed dir into components (i.e. - */ /* path to new directory and name of new directory */ - if ((fnp = split_path(path, szFileName, szFileExt)) == NULL) + if ((fnp = split_path(path, fcbname)) == NULL) { return DE_PATHNOTFND; } /* Check that we don't have a duplicate name, so if we */ /* find one, it's an error. */ - if (find_fname(fnp, szFileName, szFileExt, attrib)) + if (find_fname(fnp, fcbname, attrib)) { /* Do not delete directories or r/o files */ /* lfn entries and volume labels are only found */ @@ -566,10 +555,11 @@ COUNT dos_rmdir(BYTE * path) REG f_node_ptr fnp; REG f_node_ptr fnp1; BOOL found; + char fcbname[FNAME_SIZE + FEXT_SIZE]; /* first split the passed dir into comopnents (i.e. - */ /* path to new directory and name of new directory */ - if ((fnp = split_path(path, szFileName, szFileExt)) == NULL) + if ((fnp = split_path(path, fcbname)) == NULL) { return DE_PATHNOTFND; } @@ -583,7 +573,7 @@ COUNT dos_rmdir(BYTE * path) /* Check that we don't have a duplicate name, so if we */ /* find one, it's an error. */ - if (find_fname(fnp, szFileName, szFileExt, D_ALL)) + if (find_fname(fnp, fcbname, D_ALL)) { /* The only permissable attribute is directory, */ /* check for any other bit set. If it is, give */ @@ -658,17 +648,18 @@ COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib) REG f_node_ptr fnp2; BOOL is_free; COUNT ret; + char fcbname[FNAME_SIZE + FEXT_SIZE]; /* first split the passed target into compnents (i.e. - path to */ /* new file name and name of new file name */ - if ((fnp2 = split_path(path2, szFileName, szFileExt)) == NULL) + if ((fnp2 = split_path(path2, fcbname)) == NULL) { return DE_PATHNOTFND; } /* Check that we don't have a duplicate name, so if we find */ /* one, it's an error. */ - if (find_fname(fnp2, szFileName, szFileExt, attrib)) + if (find_fname(fnp2, fcbname, attrib)) { dir_close(fnp2); return DE_ACCESS; @@ -676,13 +667,13 @@ COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib) /* next split the passed source into compnents (i.e. - path to */ /* old file name and name of old file name */ - if ((fnp1 = split_path(path1, szFileName, szFileExt)) == NULL) + if ((fnp1 = split_path(path1, fcbname)) == NULL) { dir_close(fnp2); return DE_PATHNOTFND; } - if (!find_fname(fnp1, szFileName, szFileExt, attrib)) + if (!find_fname(fnp1, fcbname, attrib)) { /* No such file, return the error */ dir_close(fnp1); @@ -693,7 +684,7 @@ COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib) /* Reset the directory by a close followed by an open */ fnp2->f_flags.f_dmod = FALSE; dir_close(fnp2); - fnp2 = split_path(path2, szFileName, szFileExt); + fnp2 = split_path(path2, fcbname); /* Now find a free slot to put the file into. */ /* If it's the root and we don't have room, return an error. */ @@ -719,8 +710,7 @@ COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib) return ret; /* put the fnode's name into the directory. */ - memcpy(fnp2->f_dir.dir_name, szFileName, FNAME_SIZE); - memcpy(fnp2->f_dir.dir_ext, szFileExt, FEXT_SIZE); + memcpy(fnp2->f_dir.dir_name, fcbname, FNAME_SIZE + FEXT_SIZE); /* Set the fnode to the desired mode */ fnp2->f_dir.dir_size = fnp1->f_dir.dir_size; @@ -766,7 +756,7 @@ STATIC VOID wipe_out_clusters(struct dpb FAR * dpbp, CLUSTER st) next = next_cluster(dpbp, st); /* just exit if a damaged file system exists */ - if (next == FREE) + if (next == FREE || next == 1) return; /* zap the FAT pointed to */ @@ -820,15 +810,13 @@ STATIC BOOL find_free(f_node_ptr fnp) /* */ date dos_getdate() { - BYTE WeekDay, Month, MonthDay; - COUNT Year; + UBYTE WeekDay, Month, MonthDay; + UWORD Year; date Date; /* First - get the system date set by either the user */ /* on start-up or the CMOS clock */ - DosGetDate((BYTE FAR *) & WeekDay, - (BYTE FAR *) & Month, - (BYTE FAR *) & MonthDay, (COUNT FAR *) & Year); + DosGetDate(&WeekDay, &Month, &MonthDay, &Year); Date = DT_ENCODE(Month, MonthDay, Year - EPOCH_YEAR); return Date; } @@ -838,13 +826,11 @@ date dos_getdate() /* */ time dos_gettime() { - BYTE Hour, Minute, Second, Hundredth; + UBYTE Hour, Minute, Second, Hundredth; /* First - get the system time set by either the user */ /* on start-up or the CMOS clock */ - DosGetTime((BYTE FAR *) & Hour, - (BYTE FAR *) & Minute, - (BYTE FAR *) & Second, (BYTE FAR *) & Hundredth); + DosGetTime(&Hour, &Minute, &Second, &Hundredth); return TM_ENCODE(Hour, Minute, Second / 2); } @@ -901,7 +887,7 @@ COUNT dos_setftime(COUNT fd, date dp, time tp) /* */ /* dos_getfsize for the file time */ /* */ -LONG dos_getcufsize(COUNT fd) +ULONG dos_getfsize(COUNT fd) { f_node_ptr fnp; @@ -913,33 +899,12 @@ LONG dos_getcufsize(COUNT fd) /* requested file was not open, tell the caller and exit */ /* note: an invalid fd is indicated by a 0 return */ if (fnp == (f_node_ptr) 0 || fnp->f_count <= 0) - return -1l; + return (ULONG)-1l; /* Return the file size */ return fnp->f_highwater; } -/* */ -/* dos_getfsize for the file time */ -/* */ -LONG dos_getfsize(COUNT fd) -{ - f_node_ptr fnp; - - /* Translate the fd into an fnode pointer, since all internal */ - /* operations are achieved through fnodes. */ - fnp = xlt_fd(fd); - - /* If the fd was invalid because it was out of range or the */ - /* requested file was not open, tell the caller and exit */ - /* note: an invalid fd is indicated by a 0 return */ - if (fnp == (f_node_ptr) 0 || fnp->f_count <= 0) - return -1l; - - /* Return the file size */ - return fnp->f_dir.dir_size; -} - /* */ /* dos_setfsize for the file time */ /* */ @@ -1050,10 +1015,11 @@ COUNT dos_mkdir(BYTE * dir) struct dpb FAR *dpbp; CLUSTER free_fat, parent; COUNT ret; - + char fcbname[FNAME_SIZE + FEXT_SIZE]; + /* first split the passed dir into comopnents (i.e. - */ /* path to new directory and name of new directory */ - if ((fnp = split_path(dir, szFileName, szFileExt)) == NULL) + if ((fnp = split_path(dir, fcbname)) == NULL) { return DE_PATHNOTFND; } @@ -1074,7 +1040,7 @@ COUNT dos_mkdir(BYTE * dir) /* Check that we don't have a duplicate name, so if we */ /* find one, it's an error. */ - if (find_fname(fnp, szFileName, szFileExt, D_ALL)) + if (find_fname(fnp, fcbname, D_ALL)) { dir_close(fnp); return DE_ACCESS; @@ -1085,7 +1051,7 @@ COUNT dos_mkdir(BYTE * dir) fnp->f_flags.f_dmod = FALSE; parent = fnp->f_dirstart; dir_close(fnp); - fnp = split_path(dir, szFileName, szFileExt); + fnp = split_path(dir, fcbname); /* Get a free f_node pointer so that we can use */ /* it in building the new file. */ @@ -1121,8 +1087,7 @@ COUNT dos_mkdir(BYTE * dir) } /* put the fnode's name into the directory. */ - memcpy(fnp->f_dir.dir_name, szFileName, FNAME_SIZE); - memcpy(fnp->f_dir.dir_ext, szFileExt, FEXT_SIZE); + memcpy(fnp->f_dir.dir_name, fcbname, FNAME_SIZE + FEXT_SIZE); /* Set the fnode to the desired mode */ fnp->f_mode = WRONLY; @@ -1160,8 +1125,8 @@ COUNT dos_mkdir(BYTE * dir) } /* Create the "." entry */ - memcpy(DirEntBuffer.dir_name, ". ", FNAME_SIZE); - memcpy(DirEntBuffer.dir_ext, " ", FEXT_SIZE); + DirEntBuffer.dir_name[0] = '.'; + memset(DirEntBuffer.dir_name + 1, ' ', FNAME_SIZE + FEXT_SIZE - 1); DirEntBuffer.dir_attrib = D_DIR; DirEntBuffer.dir_time = dos_gettime(); DirEntBuffer.dir_date = dos_getdate(); @@ -1169,10 +1134,10 @@ COUNT dos_mkdir(BYTE * dir) DirEntBuffer.dir_size = 0l; /* And put it out */ - putdirent((struct dirent FAR *)&DirEntBuffer, (BYTE FAR *) bp->b_buffer); + putdirent(&DirEntBuffer, bp->b_buffer); /* create the ".." entry */ - memcpy(DirEntBuffer.dir_name, ".. ", FNAME_SIZE); + DirEntBuffer.dir_name[1] = '.'; #ifdef WITHFAT32 if (ISFAT32(dpbp) && parent == dpbp->dpb_xrootclst) { @@ -1182,8 +1147,7 @@ COUNT dos_mkdir(BYTE * dir) setdstart(DirEntBuffer, parent); /* and put it out */ - putdirent((struct dirent FAR *)&DirEntBuffer, - (BYTE FAR *) & bp->b_buffer[DIRENT_SIZE]); + putdirent(&DirEntBuffer, &bp->b_buffer[DIRENT_SIZE]); /* fill the rest of the block with zeros */ fmemset(&bp->b_buffer[2 * DIRENT_SIZE], 0, BUFFERSIZE - 2 * DIRENT_SIZE); @@ -1212,6 +1176,7 @@ COUNT dos_mkdir(BYTE * dir) } /* flush the drive buffers so that all info is written */ + /* hazard: no error checking! */ flush_buffers((COUNT) (dpbp->dpb_unit)); /* Close the directory so that the entry is updated */ @@ -1292,6 +1257,7 @@ STATIC COUNT extend_dir(f_node_ptr fnp) } /* flush the drive buffers so that all info is written */ + /* hazard: no error checking! */ flush_buffers((COUNT) (fnp->f_dpb->dpb_unit)); return SUCCESS; @@ -1416,6 +1382,8 @@ COUNT map_cluster(REG f_node_ptr fnp, COUNT mode) fnp->f_cluster = next_cluster(fnp->f_dpb, fnp->f_cluster); fnp->f_cluster_offset += clssize; idx -= clssize; + if (fnp->f_cluster == 1) + return DE_SEEK; } #ifdef DISPLAY_GETBLOCK @@ -1578,8 +1546,8 @@ UCOUNT rwblock(COUNT fd, VOID FAR * buffer, UCOUNT count, int mode) REG struct buffer FAR *bp; UCOUNT xfr_cnt = 0; UCOUNT ret_cnt = 0; - UWORD secsize; - UCOUNT to_xfer = count; + unsigned secsize; + unsigned to_xfer = count; ULONG currentblock; #if 0 /*DSK_DEBUG*/ @@ -1932,7 +1900,7 @@ COUNT dos_cd(struct cds FAR * cdsp, BYTE * PathName) f_node_ptr get_f_node(void) { - REG i; + REG int i; for (i = 0; i < f_nodes_cnt; i++) { @@ -1959,66 +1927,54 @@ VOID dos_setdta(BYTE FAR * newdta) dta = newdta; } -COUNT dos_getfattr(BYTE * name) +COUNT dos_getfattr_fd(COUNT fd) { - f_node_ptr fnp; - COUNT fd, result; - - /* Translate the fd into an fnode pointer, since all internal */ - /* operations are achieved through fnodes. */ - if ((fd = dos_open(name, O_RDONLY)) < SUCCESS) - return DE_FILENOTFND; + f_node_ptr fnp = xlt_fd(fd); /* note: an invalid fd is indicated by a 0 return */ - if ((fnp = xlt_fd(fd)) == (f_node_ptr) 0) + if (fnp == (f_node_ptr) 0) return DE_TOOMANY; /* If the fd was invalid because it was out of range or the */ /* requested file was not open, tell the caller and exit */ if (fnp->f_count <= 0) - { - dos_close(fd); return DE_FILENOTFND; - } - /* Get the attribute from the fnode and return */ - result = fnp->f_dir.dir_attrib; + return fnp->f_dir.dir_attrib; +} + +COUNT dos_getfattr(BYTE * name) +{ + COUNT result, fd; + + fd = (short)dos_open(name, O_RDONLY | O_OPEN, 0); + if (fd < SUCCESS) + return fd; + + result = dos_getfattr_fd(fd); dos_close(fd); return result; } COUNT dos_setfattr(BYTE * name, UWORD attrp) { - f_node_ptr fnp; COUNT fd; + f_node_ptr fnp; - /* Translate the fd into an fnode pointer, since all internal */ - /* operations are achieved through fnodes. */ - if ((fd = dos_open(name, O_RDONLY)) < SUCCESS) - return DE_FILENOTFND; - - /* note: an invalid fd is indicated by a 0 return */ - if ((fnp = xlt_fd(fd)) == (f_node_ptr) 0) - return DE_TOOMANY; - - /* If the fd was invalid because it was out of range or the */ - /* requested file was not open, tell the caller and exit */ - if (fnp->f_count <= 0) - { - dos_close(fd); - return DE_FILENOTFND; - } /* JPP-If user tries to set VOLID or DIR bits, return error */ if ((attrp & (D_VOLID | D_DIR | 0xC0)) != 0) - { - dos_close(fd); return DE_ACCESS; - } + fd = (short)dos_open(name, O_RDONLY | O_OPEN, 0); + if (fd < SUCCESS) + return fd; + + fnp = xlt_fd(fd); + /* Set the attribute from the fnode and return */ /* clear all attributes but DIR and VOLID */ fnp->f_dir.dir_attrib &= (D_VOLID | D_DIR); /* JPP */ - + /* set attributes that user requested */ fnp->f_dir.dir_attrib |= attrp; /* JPP */ fnp->f_flags.f_dmod = TRUE; @@ -2094,8 +2050,6 @@ VOID bpb_to_dpb(bpb FAR * bpbp, REG struct dpb FAR * dpbp) COUNT media_check(REG struct dpb FAR * dpbp) { - BYTE status; - /* First test if anyone has changed the removable media */ FOREVER { @@ -2105,10 +2059,8 @@ COUNT media_check(REG struct dpb FAR * dpbp) MediaReqHdr.r_mcmdesc = dpbp->dpb_mdb; MediaReqHdr.r_status = 0; execrh((request FAR *) & MediaReqHdr, dpbp->dpb_device); - if (!(MediaReqHdr.r_status & S_ERROR) - && (MediaReqHdr.r_status & S_DONE)) - break; - else + if ((MediaReqHdr.r_status & S_ERROR) + || !(MediaReqHdr.r_status & S_DONE)) { loop1: switch (block_error(&MediaReqHdr, dpbp->dpb_unit, dpbp->dpb_device)) @@ -2127,10 +2079,10 @@ COUNT media_check(REG struct dpb FAR * dpbp) goto loop1; } } + break; } - status = MediaReqHdr.r_mcretcode | dpbp->dpb_flags; - switch (status) + switch (MediaReqHdr.r_mcretcode | dpbp->dpb_flags) { case M_NOT_CHANGED: /* It was definitely not changed, so ignore it */ @@ -2139,6 +2091,7 @@ COUNT media_check(REG struct dpb FAR * dpbp) /* If it is forced or the media may have changed, */ /* rebuild the bpb */ case M_DONT_KNOW: + /* hazard: no error checking! */ flush_buffers(dpbp->dpb_unit); /* If it definitely changed, don't know (falls through) */ @@ -2154,10 +2107,8 @@ COUNT media_check(REG struct dpb FAR * dpbp) MediaReqHdr.r_mcmdesc = dpbp->dpb_mdb; MediaReqHdr.r_status = 0; execrh((request FAR *) & MediaReqHdr, dpbp->dpb_device); - if (!(MediaReqHdr.r_status & S_ERROR) - && (MediaReqHdr.r_status & S_DONE)) - break; - else + if ((MediaReqHdr.r_status & S_ERROR) + || !(MediaReqHdr.r_status & S_DONE)) { loop2: switch (block_error @@ -2177,6 +2128,7 @@ COUNT media_check(REG struct dpb FAR * dpbp) goto loop2; } } + break; } #ifdef WITHFAT32 /* extend dpb only for internal or FAT32 devices */ @@ -2185,9 +2137,6 @@ COUNT media_check(REG struct dpb FAR * dpbp) #else bpb_to_dpb(MediaReqHdr.r_bpptr, dpbp); #endif - /* need to change to root directory if changed */ - if (status == M_CHANGED) - CDSp[dpbp->dpb_unit].cdsCurrentPath[3] = '\0'; return SUCCESS; } } @@ -2249,7 +2198,7 @@ STATIC VOID shrink_file(f_node_ptr fnp) next = next_cluster(dpbp, st); - if (next == LONG_LAST_CLUSTER) /* last cluster found */ + if (next == 1 || next == LONG_LAST_CLUSTER) /* error last cluster found */ goto done; /* Loop from start until either a FREE entry is */ diff --git a/kernel/fcbfns.c b/kernel/fcbfns.c index a575a97..c010ff6 100644 --- a/kernel/fcbfns.c +++ b/kernel/fcbfns.c @@ -36,38 +36,30 @@ static BYTE *RcsId = #define FCB_SUCCESS 0 #define FCB_ERR_NODATA 1 +#define FCB_ERR_SEGMENT_WRAP 2 #define FCB_ERR_EOF 3 -#define FCB_ERR_WRITE 1 +#define FCB_ERROR 0xff -#ifdef PROTO -fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb); -fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer, +STATIC fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb); +STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer, COUNT * pCurDrive); -void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive); -VOID FcbNextRecord(fcb FAR * lpFcb); -BOOL FcbCalcRec(xfcb FAR * lpXfcb); -#else -fcb FAR *ExtFcbToFcb(); -fcb FAR *CommonFcbInit(); -void FcbNameInit(); -VOID FcbNextRecord(); -BOOL FcbCalcRec(); -#endif +STATIC int FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive); +STATIC void FcbNextRecord(fcb FAR * lpFcb); +STATIC void FcbCalcRec(xfcb FAR * lpXfcb); -#define TestCmnSeps(lpFileName) (strchr(":<|>+=,", *lpFileName) != NULL) -#define TestFieldSeps(lpFileName) (*(lpFileName) <= ' ' || strchr("/\"[]<>|.", *lpFileName) != NULL) +#define TestCmnSeps(lpFileName) (*lpFileName && strchr(":<|>+=,", *lpFileName) != NULL) +#define TestFieldSeps(lpFileName) ((unsigned char)*lpFileName <= ' ' || strchr("/\"[]<>|.", *lpFileName) != NULL) static dmatch Dmatch; -VOID FatGetDrvData(UCOUNT drive, UCOUNT FAR * spc, UCOUNT FAR * bps, - UCOUNT FAR * nc, BYTE FAR ** mdp) +BYTE FAR *FatGetDrvData(UBYTE drive, UWORD * spc, UWORD * bps, UWORD * nc) { static BYTE mdb; - UCOUNT navc; + UWORD navc; /* get the data available from dpb */ *nc = 0xffff; /* pass 0xffff to skip free count */ - if (DosGetFree((UBYTE) drive, spc, &navc, bps, nc)) + if (DosGetFree(drive, spc, &navc, bps, nc)) { struct cds FAR *cdsp = &CDSp[(drive == 0 ? default_drive : drive - 1)]; @@ -75,14 +67,15 @@ VOID FatGetDrvData(UCOUNT drive, UCOUNT FAR * spc, UCOUNT FAR * bps, if (cdsp->cdsFlags & CDSNETWDRV) { mdb = *spc >> 8; - *mdp = &mdb; *spc &= 0xff; + return &mdb; } else { - *mdp = (BYTE FAR *) & (cdsp->cdsDpb->dpb_mdb); + return (BYTE FAR *) & (cdsp->cdsDpb->dpb_mdb); } } + return NULL; } #define PARSE_SEP_STOP 0x01 @@ -95,78 +88,81 @@ VOID FatGetDrvData(UCOUNT drive, UCOUNT FAR * spc, UCOUNT FAR * bps, #define PARSE_RET_BADDRIVE 0xff #ifndef IPL -WORD FcbParseFname(int wTestMode, const BYTE FAR ** lpFileName, fcb FAR * lpFcb) +UWORD FcbParseFname(int *wTestMode, const BYTE FAR * lpFileName, fcb FAR * lpFcb) { - COUNT nIndex; WORD wRetCodeName = FALSE, wRetCodeExt = FALSE; + const BYTE FAR * lpFileName2 = lpFileName; /* pjv -- ExtFcbToFcb? */ /* Start out with some simple stuff first. Check if we are */ /* going to use a default drive specificaton. */ - if (!(wTestMode & PARSE_DFLT_DRIVE)) + if (!(*wTestMode & PARSE_DFLT_DRIVE)) lpFcb->fcb_drive = FDFLT_DRIVE; - if (!(wTestMode & PARSE_BLNK_FNAME)) + if (!(*wTestMode & PARSE_BLNK_FNAME)) { - for (nIndex = 0; nIndex < FNAME_SIZE; ++nIndex) - lpFcb->fcb_fname[nIndex] = ' '; + fmemset(lpFcb->fcb_fname, ' ', FNAME_SIZE); } - if (!(wTestMode & PARSE_BLNK_FEXT)) + if (!(*wTestMode & PARSE_BLNK_FEXT)) { - for (nIndex = 0; nIndex < FEXT_SIZE; ++nIndex) - lpFcb->fcb_fext[nIndex] = ' '; + fmemset(lpFcb->fcb_fext, ' ', FEXT_SIZE); } /* Undocumented behavior, set record number & record size to 0 */ lpFcb->fcb_cublock = lpFcb->fcb_recsiz = 0; - if (!(wTestMode & PARSE_SEP_STOP)) + if (!(*wTestMode & PARSE_SEP_STOP)) { - *lpFileName = ParseSkipWh(*lpFileName); - if (TestCmnSeps(*lpFileName)) - ++ * lpFileName; + lpFileName2 = ParseSkipWh(lpFileName2); + if (TestCmnSeps(lpFileName2)) + ++lpFileName2; } /* Undocumented "feature," we skip white space anyway */ - *lpFileName = ParseSkipWh(*lpFileName); + lpFileName2 = ParseSkipWh(lpFileName2); /* Now check for drive specification */ - if (*(*lpFileName + 1) == ':') + if (*(lpFileName2 + 1) == ':') { /* non-portable construct to be changed */ - REG UBYTE Drive = DosUpFChar(**lpFileName) - 'A'; + REG UBYTE Drive = DosUpFChar(*lpFileName2) - 'A'; if (Drive >= lastdrive) - return PARSE_RET_BADDRIVE; + { + *wTestMode = PARSE_RET_BADDRIVE; + return lpFileName2 - lpFileName; + } lpFcb->fcb_drive = Drive + 1; - *lpFileName += 2; + lpFileName2 += 2; } /* special cases: '.' and '..' */ - if (**lpFileName == '.') + if (*lpFileName2 == '.') { lpFcb->fcb_fname[0] = '.'; - ++*lpFileName; - if (**lpFileName == '.') + ++lpFileName2; + if (*lpFileName2 == '.') { lpFcb->fcb_fname[1] = '.'; - ++*lpFileName; + ++lpFileName2; } - return PARSE_RET_NOWILD; + *wTestMode = PARSE_RET_NOWILD; + return lpFileName2 - lpFileName; } /* Now to format the file name into the string */ - *lpFileName = - GetNameField(*lpFileName, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE, + lpFileName2 = + GetNameField(lpFileName2, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE, (BOOL *) & wRetCodeName); /* Do we have an extension? If do, format it else return */ - if (**lpFileName == '.') - *lpFileName = - GetNameField(++*lpFileName, (BYTE FAR *) lpFcb->fcb_fext, + if (*lpFileName2 == '.') + lpFileName2 = + GetNameField(++lpFileName2, (BYTE FAR *) lpFcb->fcb_fext, FEXT_SIZE, (BOOL *) & wRetCodeExt); - return (wRetCodeName | wRetCodeExt) ? PARSE_RET_WILD : PARSE_RET_NOWILD; + *wTestMode = (wRetCodeName | wRetCodeExt) ? PARSE_RET_WILD : PARSE_RET_NOWILD; + return lpFileName2 - lpFileName; } const BYTE FAR * ParseSkipWh(const BYTE FAR * lpFileName) @@ -229,8 +225,7 @@ const BYTE FAR * GetNameField(const BYTE FAR * lpFileName, BYTE FAR * lpDestFiel } /* Blank out remainder of field on exit */ - for (; nIndex < nFieldSize; ++nIndex) - *lpDestField++ = cFill; + fmemset(lpDestField, cFill, nFieldSize - nIndex); return lpFileName; } @@ -248,109 +243,55 @@ STATIC ULONG FcbRec(VOID) return ((ULONG) lpFcb->fcb_cublock * 128) + lpFcb->fcb_curec; } -BOOL FcbRead(xfcb FAR * lpXfcb, COUNT * nErrorCode, UCOUNT recno) +UBYTE FcbReadWrite(xfcb FAR * lpXfcb, UCOUNT recno, int mode) { sft FAR *s; ULONG lPosit; - COUNT nRead; + UCOUNT nTransfer; BYTE far * FcbIoPtr = dta + recno * lpFcb->fcb_recsiz; + if ((ULONG)recno * lpFcb->fcb_recsiz >= 0x10000ul || + FP_OFF(FcbIoPtr) < FP_OFF(dta)) + return FCB_ERR_SEGMENT_WRAP; + /* Convert to fcb if necessary */ lpFcb = ExtFcbToFcb(lpXfcb); - + /* Get the SFT block that contains the SFT */ if ((s = idx_to_sft(lpFcb->fcb_sftno)) == (sft FAR *) - 1) - return FALSE; + return FCB_ERR_NODATA; /* If this is not opened another error */ if (s->sft_count == 0) - return FALSE; - + return FCB_ERR_NODATA; + /* Now update the fcb and compute where we need to position */ /* to. */ lPosit = FcbRec() * lpFcb->fcb_recsiz; - if (SftSeek(s, lPosit, 0) != SUCCESS) - { - *nErrorCode = FCB_ERR_EOF; - return FALSE; - } + if ((CritErrCode = -SftSeek(s, lPosit, 0)) != SUCCESS) + return FCB_ERR_NODATA; /* Do the read */ - nRead = DosReadSft(s, lpFcb->fcb_recsiz, FcbIoPtr, nErrorCode); - + nTransfer = DosRWSft(s, lpFcb->fcb_recsiz, FcbIoPtr, &CritErrCode, mode); + CritErrCode = -CritErrCode; + /* Now find out how we will return and do it. */ - if (nRead == lpFcb->fcb_recsiz) + if (nTransfer == lpFcb->fcb_recsiz) { - *nErrorCode = FCB_SUCCESS; + if (mode == XFR_WRITE) lpFcb->fcb_fsize = s->sft_size; FcbNextRecord(lpFcb); - return TRUE; + return FCB_SUCCESS; } - else if (nRead < 0) + if (mode == XFR_READ && nTransfer > 0) { - *nErrorCode = FCB_ERR_EOF; - return TRUE; - } - else if (nRead == 0) - { - *nErrorCode = FCB_ERR_NODATA; - return FALSE; - } - else - { - fmemset(FcbIoPtr + nRead, 0, lpFcb->fcb_recsiz - nRead); - *nErrorCode = FCB_ERR_EOF; + fmemset(FcbIoPtr + nTransfer, 0, lpFcb->fcb_recsiz - nTransfer); FcbNextRecord(lpFcb); - return FALSE; + return FCB_ERR_EOF; } + return FCB_ERR_NODATA; } -BOOL FcbWrite(xfcb FAR * lpXfcb, COUNT * nErrorCode, UCOUNT recno) -{ - sft FAR *s; - ULONG lPosit; - COUNT nWritten; - BYTE far * FcbIoPtr = dta + recno * lpFcb->fcb_recsiz; - - /* Convert to fcb if necessary */ - lpFcb = ExtFcbToFcb(lpXfcb); - - /* Get the SFT block that contains the SFT */ - if ((s = idx_to_sft(lpFcb->fcb_sftno)) == (sft FAR *) - 1) - return FALSE; - - /* If this is not opened another error */ - if (s->sft_count == 0) - return FALSE; - - /* Now update the fcb and compute where we need to position */ - /* to. */ - lPosit = FcbRec() * lpFcb->fcb_recsiz; - if (SftSeek(s, lPosit, 0) != SUCCESS) - { - *nErrorCode = FCB_ERR_EOF; - return FALSE; - } - - nWritten = DosWriteSft(s, lpFcb->fcb_recsiz, FcbIoPtr, nErrorCode); - - /* Now find out how we will return and do it. */ - if (nWritten == lpFcb->fcb_recsiz) - { - lpFcb->fcb_fsize = s->sft_size; - FcbNextRecord(lpFcb); - *nErrorCode = FCB_SUCCESS; - return TRUE; - } - else if (nWritten <= 0) - { - *nErrorCode = FCB_ERR_WRITE; - return TRUE; - } - *nErrorCode = FCB_ERR_WRITE; - return FALSE; -} - -BOOL FcbGetFileSize(xfcb FAR * lpXfcb) +UBYTE FcbGetFileSize(xfcb FAR * lpXfcb) { COUNT FcbDrive, hndl; @@ -358,11 +299,10 @@ BOOL FcbGetFileSize(xfcb FAR * lpXfcb) lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); /* check for a device */ - if (IsDevice(SecPathName) || (lpFcb->fcb_recsiz == 0)) - { - return FALSE; - } - hndl = DosOpen(SecPathName, O_RDONLY); + if (!lpFcb || IsDevice(SecPathName) || (lpFcb->fcb_recsiz == 0)) + return FCB_ERROR; + + hndl = (short)DosOpen(SecPathName, O_LEGACY | O_RDONLY | O_OPEN, 0); if (hndl >= 0) { ULONG fsize; @@ -376,13 +316,15 @@ BOOL FcbGetFileSize(xfcb FAR * lpXfcb) ++lpFcb->fcb_rndm; /* close the file and leave */ - return DosClose(hndl) == SUCCESS; + if ((CritErrCode = -DosClose(hndl)) == SUCCESS) + return FCB_SUCCESS; } else - return FALSE; + CritErrCode = -hndl; + return FCB_ERROR; } -BOOL FcbSetRandom(xfcb FAR * lpXfcb) +void FcbSetRandom(xfcb FAR * lpXfcb) { /* Convert to fcb if necessary */ lpFcb = ExtFcbToFcb(lpXfcb); @@ -390,11 +332,9 @@ BOOL FcbSetRandom(xfcb FAR * lpXfcb) /* Now update the fcb and compute where we need to position */ /* to. */ lpFcb->fcb_rndm = FcbRec(); - - return TRUE; } -BOOL FcbCalcRec(xfcb FAR * lpXfcb) +void FcbCalcRec(xfcb FAR * lpXfcb) { /* Convert to fcb if necessary */ @@ -404,14 +344,12 @@ BOOL FcbCalcRec(xfcb FAR * lpXfcb) /* to. */ lpFcb->fcb_cublock = lpFcb->fcb_rndm / 128; lpFcb->fcb_curec = lpFcb->fcb_rndm & 127; - - return TRUE; } -BOOL FcbRandomBlockRead(xfcb FAR * lpXfcb, COUNT nRecords, - COUNT * nErrorCode) +UBYTE FcbRandomBlockIO(xfcb FAR * lpXfcb, COUNT nRecords, int mode) { UCOUNT recno = 0; + UBYTE nErrorCode; FcbCalcRec(lpXfcb); @@ -419,39 +357,20 @@ BOOL FcbRandomBlockRead(xfcb FAR * lpXfcb, COUNT nRecords, lpFcb = ExtFcbToFcb(lpXfcb); do - FcbRead(lpXfcb, nErrorCode, recno++); - while ((--nRecords > 0) && (*nErrorCode == 0)); + nErrorCode = FcbReadWrite(lpXfcb, recno++, mode); + while ((--nRecords > 0) && (nErrorCode == 0)); /* Now update the fcb */ lpFcb->fcb_rndm = FcbRec(); - return TRUE; + return nErrorCode; } -BOOL FcbRandomBlockWrite(xfcb FAR * lpXfcb, COUNT nRecords, - COUNT * nErrorCode) -{ - UCOUNT recno = 0; - - FcbCalcRec(lpXfcb); - - /* Convert to fcb if necessary */ - lpFcb = ExtFcbToFcb(lpXfcb); - - do - FcbWrite(lpXfcb, nErrorCode, recno++); - while ((--nRecords > 0) && (*nErrorCode == 0)); - - /* Now update the fcb */ - lpFcb->fcb_rndm = FcbRec(); - - return TRUE; -} - -BOOL FcbRandomIO(xfcb FAR * lpXfcb, COUNT * nErrorCode, FcbFunc_t *FcbFunc) +UBYTE FcbRandomIO(xfcb FAR * lpXfcb, int mode) { UWORD uwCurrentBlock; UBYTE ucCurrentRecord; + UBYTE nErrorCode; FcbCalcRec(lpXfcb); @@ -461,39 +380,35 @@ BOOL FcbRandomIO(xfcb FAR * lpXfcb, COUNT * nErrorCode, FcbFunc_t *FcbFunc) uwCurrentBlock = lpFcb->fcb_cublock; ucCurrentRecord = lpFcb->fcb_curec; - (*FcbFunc) (lpXfcb, nErrorCode, 0); + nErrorCode = FcbReadWrite(lpXfcb, 0, mode); lpFcb->fcb_cublock = uwCurrentBlock; lpFcb->fcb_curec = ucCurrentRecord; - return TRUE; + return nErrorCode; } /* merged fcbOpen and FcbCreate - saves ~200 byte */ -BOOL FcbOpenCreate(xfcb FAR * lpXfcb, BOOL Create) +UBYTE FcbOpen(xfcb FAR * lpXfcb, unsigned flags) { sft FAR *sftp; COUNT sft_idx, FcbDrive; + unsigned attr = 0; /* Build a traditional DOS file name */ - lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); + if (lpFcb == NULL) + return FCB_ERROR; - if (Create) - { + if ((flags & O_CREAT) && lpXfcb->xfcb_flag == 0xff) /* pass attribute without constraints (dangerous for directories) */ - int attr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : 0); - sft_idx = DosCreatSft(PriPathName, attr); - } - else - { - sft_idx = DosOpenSft(PriPathName, O_RDWR | SFT_MFCB); - - /* if file is RDONLY, try to open rdonly */ - if (sft_idx == DE_ACCESS) - sft_idx = DosOpenSft(PriPathName, O_RDONLY | SFT_MFCB); - } + attr = lpXfcb->xfcb_attrib; + sft_idx = (short)DosOpenSft(SecPathName, flags, attr); if (sft_idx < 0) - return FALSE; + { + CritErrCode = -sft_idx; + return FCB_ERROR; + } sftp = idx_to_sft(sft_idx); sftp->sft_mode |= SFT_MFCB; @@ -511,7 +426,7 @@ BOOL FcbOpenCreate(xfcb FAR * lpXfcb, BOOL Create) lpFcb->fcb_fsize = sftp->sft_size; lpFcb->fcb_date = sftp->sft_date; lpFcb->fcb_time = sftp->sft_time; - return TRUE; + return FCB_SUCCESS; } @@ -532,13 +447,14 @@ STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer, lpFcb = ExtFcbToFcb(lpExtFcb); /* Build a traditional DOS file name */ - FcbNameInit(lpFcb, pszBuffer, pCurDrive); + if (FcbNameInit(lpFcb, pszBuffer, pCurDrive) < SUCCESS) + return NULL; /* and return the fcb pointer */ return lpFcb; } -void FcbNameInit(fcb FAR * lpFcb, BYTE * szBuffer, COUNT * pCurDrive) +int FcbNameInit(fcb FAR * lpFcb, BYTE * szBuffer, COUNT * pCurDrive) { BYTE loc_szBuffer[2 + FNAME_SIZE + 1 + FEXT_SIZE + 1]; /* 'A:' + '.' + '\0' */ BYTE *pszBuffer = loc_szBuffer; @@ -556,85 +472,83 @@ void FcbNameInit(fcb FAR * lpFcb, BYTE * szBuffer, COUNT * pCurDrive) *pCurDrive = default_drive + 1; } ConvertName83ToNameSZ(pszBuffer, (BYTE FAR *) lpFcb->fcb_fname); - truename(loc_szBuffer, szBuffer, FALSE); - /* XXX fix truename error handling */ + return truename(loc_szBuffer, szBuffer, CDS_MODE_CHECK_DEV_PATH); } -BOOL FcbDelete(xfcb FAR * lpXfcb) +UBYTE FcbDelete(xfcb FAR * lpXfcb) { COUNT FcbDrive; + UBYTE result = FCB_SUCCESS; + BYTE FAR *lpOldDta = dta; /* Build a traditional DOS file name */ CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); - /* check for a device */ - if (IsDevice(SecPathName)) + if (lpFcb == NULL || IsDevice(SecPathName)) { - return FALSE; + result = FCB_ERROR; } else { - int attr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : D_ALL); - BYTE FAR *lpOldDta = dta; + int attr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : D_ALL); dmatch Dmatch; dta = (BYTE FAR *) & Dmatch; - if (DosFindFirst(attr, SecPathName) != SUCCESS) + if ((CritErrCode = -DosFindFirst(attr, SecPathName)) != SUCCESS) { - dta = lpOldDta; - return FALSE; + result = FCB_ERROR; } - do + else do { SecPathName[0] = 'A' + FcbDrive - 1; SecPathName[1] = ':'; strcpy(&SecPathName[2], Dmatch.dm_name); if (DosDelete(SecPathName, attr) != SUCCESS) { - dta = lpOldDta; - return FALSE; + result = FCB_ERROR; + break; } } - while (DosFindNext() == SUCCESS); - dta = lpOldDta; - return TRUE; + while ((CritErrCode = -DosFindNext()) == SUCCESS); } + dta = lpOldDta; + return result; } -BOOL FcbRename(xfcb FAR * lpXfcb) +UBYTE FcbRename(xfcb FAR * lpXfcb) { rfcb FAR *lpRenameFcb; COUNT FcbDrive; + UBYTE result = FCB_SUCCESS; + BYTE FAR *lpOldDta = dta; /* Build a traditional DOS file name */ lpRenameFcb = (rfcb FAR *) CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); - wAttr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : D_ALL); - + /* check for a device */ - if (IsDevice(SecPathName)) + if (lpRenameFcb == NULL || IsDevice(SecPathName)) { - return FALSE; + result = FCB_ERROR; } else { - BYTE FAR *lpOldDta = dta; dmatch Dmatch; + COUNT result; + wAttr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : D_ALL); dta = (BYTE FAR *) & Dmatch; - if (DosFindFirst(wAttr, SecPathName) != SUCCESS) + if ((CritErrCode = -DosFindFirst(wAttr, SecPathName)) != SUCCESS) { - dta = lpOldDta; - return FALSE; + result = FCB_ERROR; } - - do + else do { fcb LocalFcb; BYTE *pToName; const BYTE FAR *pFromPattern = Dmatch.dm_name; - int i; + int i = 0; - FcbParseFname(0, &pFromPattern, &LocalFcb); + FcbParseFname(&i, pFromPattern, &LocalFcb); /* Overlay the pattern, skipping '?' */ /* I'm cheating because this assumes that the */ /* struct alignments are on byte boundaries */ @@ -651,22 +565,32 @@ BOOL FcbRename(xfcb FAR * lpXfcb) SecPathName[0] = 'A' + FcbDrive - 1; SecPathName[1] = ':'; strcpy(&SecPathName[2], Dmatch.dm_name); - truename(SecPathName, PriPathName, FALSE); + result = truename(SecPathName, PriPathName, 0); + if (result < SUCCESS || (result & IS_DEVICE)) + { + result = FCB_ERROR; + break; + } /* now to build a dos name again */ LocalFcb.fcb_drive = FcbDrive; - FcbNameInit((fcb FAR *) & LocalFcb, SecPathName, &FcbDrive); + result = FcbNameInit((fcb FAR *) & LocalFcb, SecPathName, &FcbDrive); + if (result < SUCCESS || (!(result & IS_NETWORK) && (result & IS_DEVICE))) + { + result = FCB_ERROR; + break; + } if (DosRenameTrue(PriPathName, SecPathName, wAttr) != SUCCESS) { - dta = lpOldDta; - return FALSE; + result = FCB_ERROR; + break; } } - while (DosFindNext() == SUCCESS); - dta = lpOldDta; - return TRUE; + while ((CritErrCode = -DosFindNext()) == SUCCESS); } + dta = lpOldDta; + return result; } /* TE:the MoveDirInfo() is now done by simply copying the dirEntry into the FCB @@ -674,7 +598,7 @@ BOOL FcbRename(xfcb FAR * lpXfcb) BO:use global SearchDir, as produced by FindFirst/Next */ -BOOL FcbClose(xfcb FAR * lpXfcb) +UBYTE FcbClose(xfcb FAR * lpXfcb) { sft FAR *s; @@ -683,23 +607,23 @@ BOOL FcbClose(xfcb FAR * lpXfcb) /* An already closed FCB can be closed again without error */ if (lpFcb->fcb_sftno == (BYTE) 0xff) - return TRUE; + return FCB_SUCCESS; /* Get the SFT block that contains the SFT */ if ((s = idx_to_sft(lpFcb->fcb_sftno)) == (sft FAR *) - 1) - return FALSE; + return FCB_ERROR; /* change time and set file size */ s->sft_size = lpFcb->fcb_fsize; if (!(s->sft_flags & SFT_FSHARED)) dos_setfsize(s->sft_status, lpFcb->fcb_fsize); DosSetFtimeSft(lpFcb->fcb_sftno, lpFcb->fcb_date, lpFcb->fcb_time); - if (DosCloseSft(lpFcb->fcb_sftno, FALSE) == SUCCESS) + if ((CritErrCode = -DosCloseSft(lpFcb->fcb_sftno, FALSE)) == SUCCESS) { lpFcb->fcb_sftno = (BYTE) 0xff; - return TRUE; + return FCB_SUCCESS; } - return FALSE; + return FCB_ERROR; } /* close all files the current process opened by FCBs */ @@ -713,7 +637,7 @@ VOID FcbCloseAll() DosCloseSft(idx, FALSE); } -BOOL FcbFindFirst(xfcb FAR * lpXfcb) +UBYTE FcbFindFirstNext(xfcb FAR * lpXfcb, BOOL First) { BYTE FAR *lpDir; COUNT FcbDrive; @@ -726,31 +650,45 @@ BOOL FcbFindFirst(xfcb FAR * lpXfcb) /* Next initialze local variables by moving them from the fcb */ lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); - if (lpXfcb->xfcb_flag == 0xff) + if (lpFcb == NULL) + return FCB_ERROR; + + /* Reconstrct the dirmatch structure from the fcb - doesn't hurt for first */ + Dmatch.dm_drive = lpFcb->fcb_sftno; + + fmemcpy(Dmatch.dm_name_pat, lpFcb->fcb_fname, FNAME_SIZE + FEXT_SIZE); + DosUpFMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); + + Dmatch.dm_attr_srch = wAttr; + Dmatch.dm_entry = lpFcb->fcb_strtclst; + Dmatch.dm_dircluster = lpFcb->fcb_dirclst; + + wAttr = D_ALL; + + if ((xfcb FAR *) lpFcb != lpXfcb) { wAttr = lpXfcb->xfcb_attrib; fmemcpy(lpDir, lpXfcb, 7); lpDir += 7; } - else - wAttr = D_ALL; - if (DosFindFirst(wAttr, SecPathName) != SUCCESS) + CritErrCode = -(First ? DosFindFirst(wAttr, SecPathName) : DosFindNext()); + if (CritErrCode != SUCCESS) { dta = lpPsp->ps_dta; - return FALSE; + return FCB_ERROR; } *lpDir++ = FcbDrive; fmemcpy(lpDir, &SearchDir, sizeof(struct dirent)); - + lpFcb->fcb_dirclst = (UWORD) Dmatch.dm_dircluster; lpFcb->fcb_strtclst = Dmatch.dm_entry; - + /* - This is undocumented and seen using Pcwatch and Ramview. - The First byte is the current directory count and the second seems - to be the attribute byte. + This is undocumented and seen using Pcwatch and Ramview. + The First byte is the current directory count and the second seems + to be the attribute byte. */ lpFcb->fcb_sftno = Dmatch.dm_drive; /* MSD seems to save this @ fcb_date. */ #if 0 @@ -758,66 +696,8 @@ BOOL FcbFindFirst(xfcb FAR * lpXfcb) lpFcb->fcb_cublock *= 0x100; lpFcb->fcb_cublock += wAttr; #endif - dta = lpPsp->ps_dta; - return TRUE; -} - -BOOL FcbFindNext(xfcb FAR * lpXfcb) -{ - BYTE FAR *lpDir; - COUNT FcbDrive; - psp FAR *lpPsp = MK_FP(cu_psp, 0); - - /* First, move the dta to a local and change it around to match */ - /* our functions. */ - lpDir = (BYTE FAR *) dta; - dta = (BYTE FAR *) & Dmatch; - - /* Next initialze local variables by moving them from the fcb */ - lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); - - /* Reconstrct the dirmatch structure from the fcb */ - Dmatch.dm_drive = lpFcb->fcb_sftno; - - fmemcpy(Dmatch.dm_name_pat, lpFcb->fcb_fname, FNAME_SIZE + FEXT_SIZE); - DosUpFMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); - - Dmatch.dm_attr_srch = wAttr; - Dmatch.dm_entry = lpFcb->fcb_strtclst; - Dmatch.dm_dircluster = lpFcb->fcb_dirclst; - - if ((xfcb FAR *) lpFcb != lpXfcb) - { - wAttr = lpXfcb->xfcb_attrib; - fmemcpy(lpDir, lpXfcb, 7); - lpDir += 7; - } - else - wAttr = D_ALL; - - if (DosFindNext() != SUCCESS) - { - dta = lpPsp->ps_dta; - CritErrCode = 0x12; - return FALSE; - } - - *lpDir++ = FcbDrive; - fmemcpy((struct dirent FAR *)lpDir, &SearchDir, sizeof(struct dirent)); - - lpFcb->fcb_dirclst = (UWORD) Dmatch.dm_dircluster; - lpFcb->fcb_strtclst = Dmatch.dm_entry; - - lpFcb->fcb_sftno = Dmatch.dm_drive; -#if 0 - lpFcb->fcb_cublock = Dmatch.dm_entry; - lpFcb->fcb_cublock *= 0x100; - lpFcb->fcb_cublock += wAttr; -#endif - - dta = lpPsp->ps_dta; - return TRUE; + return FCB_SUCCESS; } #endif diff --git a/kernel/globals.h b/kernel/globals.h index e753166..91891e3 100644 --- a/kernel/globals.h +++ b/kernel/globals.h @@ -307,15 +307,7 @@ extern struct /* Path name parsing buffer */ BYTE _PriPathName[128]; } ASM _PriPathBuffer; -extern struct { - BYTE _fname[FNAME_SIZE]; - BYTE _fext[FEXT_SIZE + 1]; /* space for 0 */ -} ASM szNames; - #define PriPathName _PriPathBuffer._PriPathName -#define szDirName TempCDS.cdsCurrentPath -#define szFileName szNames._fname -#define szFileExt szNames._fext extern struct /* Alternate path name parsing buffer */ { @@ -440,25 +432,15 @@ COUNT con(); #define fputword(vp, w) (*(UWORD FAR *)(vp)=w) #define fputbyte(vp, b) (*(UBYTE FAR *)(vp)=b) #else -#ifdef PROTO -WORD getword(VOID *); -BYTE getbyte(VOID *); -LONG fgetlong(VOID FAR *); -WORD fgetword(VOID FAR *); -BYTE fgetbyte(VOID FAR *); +UDWORD getlong(VOID *); +UWORD getword(VOID *); +UBYTE getbyte(VOID *); +UDWORD fgetlong(VOID FAR *); +UWORD fgetword(VOID FAR *); +UBYTE fgetbyte(VOID FAR *); VOID fputlong(VOID FAR *, UDWORD); VOID fputword(VOID FAR *, UWORD); VOID fputbyte(VOID FAR *, UBYTE); -#else -VOID getword(); -VOID getbyte(); -VOID fgetlong(); -VOID fgetword(); -VOID fgetbyte(); -VOID fputlong(); -VOID fputword(); -VOID fputbyte(); -#endif #endif #ifdef I86 diff --git a/kernel/init-dat.h b/kernel/init-dat.h index e51d1df..d9ae9b6 100644 --- a/kernel/init-dat.h +++ b/kernel/init-dat.h @@ -20,7 +20,13 @@ extern __segment DosTextSeg; #define DOSFAR FAR #define DOSTEXTFAR FAR +#elif !defined(I86) + +#define DOSFAR +#define DOSTEXTFAR + #else + #pragma error("unknown compiler - please adjust") this should simply not compile ! ! #endif diff --git a/kernel/int2f.asm b/kernel/int2f.asm index 112f540..cc33659 100644 --- a/kernel/int2f.asm +++ b/kernel/int2f.asm @@ -106,7 +106,7 @@ IntDosCal: ; UWORD ip,cs,flags; ; UWORD callerARG1; ;}; - Protect386Registers + Protect386Registers push ax push cx push dx @@ -131,7 +131,7 @@ IntDosCal: pop dx pop cx pop ax - Restore386Registers + Restore386Registers iret @@ -255,6 +255,11 @@ _QRemote_Fn global _remote_printredir _remote_printredir: mov al, 25h + jmp short call_int2f + + global _remote_extopen +_remote_extopen: + mov al, 2eh call_int2f: mov ah, 11h @@ -263,7 +268,6 @@ call_int2f: push es push si push di - push dx push cx push bx @@ -275,10 +279,6 @@ call_int2f: je print_doredir cmp al, 1fh je print_doredir - cmp al, 21h ; 21h, Lseek from eof - je lseekeof - cmp al, 23h - je qremote_fn cmp al, 25h je remote_printredir @@ -289,22 +289,27 @@ call_int2f: je remote_rw cmp al, 0ch je remote_getfree + cmp al, 21h ; 21h, Lseek from eof + je lseekeof + cmp al, 23h + je qremote_fn int2f_call_push: push word [bp+8] ; very fakey, HaHa ;) int2f_call: - clc ; set to succeed + xor cx, cx ; set to succeed; clear carry and CX int 2fh pop bx jc no_clear_ax clear_ax: - xor ax,ax + mov ax, cx ; extended open -> status from CX in AX + ; otherwise CX was set to zero above + jmp short no_neg_ax no_clear_ax: neg ax no_neg_ax: pop bx pop cx - pop dx pop di pop si pop es @@ -314,8 +319,8 @@ no_neg_ax: lseekeof: mov dx, [bp+8] mov cx, [bp+10] - jmp int2f_call_push - + ; "fall through" + remote_getfattr: clc ; set to succeed int 2fh @@ -358,17 +363,20 @@ remote_printredir: mov dx, [bp+4] push word [bp+6] jmp short int2f_call + +remote_rw: jmp short remote_rw1 -qremote_fn: - lds si,[bp+4] - les di,[bp+8] +qremote_fn: + push ds + lds si,[bp+8] clc int 2fh + pop ds mov ax,0xffff jc no_neg_ax jmp short clear_ax -remote_rw: mov cx, [bp+8] +remote_rw1: mov cx, [bp+8] clc ; set to succeed int 2fh jc int2f_carry @@ -377,7 +385,7 @@ int2f_carry: neg ax mov di, [bp+10] mov [di], ax mov ax, cx - jmp short no_neg_ax + jmp no_neg_ax global _remote_process_end _remote_process_end: ; Terminate process diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index bbcfff3..d33ab91 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -30,6 +30,7 @@ #include "portab.h" #include "globals.h" +#include "nls.h" #ifdef VERSION_STRINGS BYTE *RcsId = @@ -58,10 +59,6 @@ struct HugeSectorBlock { BYTE FAR *buf; }; -/* must be global/file scope, Turbo C uses the wrong segment for - * function scope */ -STATIC const char dbcsTable[] = {0, 0, 0, 0}; - /* Normal entry. This minimizes user stack usage by avoiding local */ /* variables needed for the rest of the handler. */ /* this here works on the users stack !! and only very few functions @@ -156,17 +153,237 @@ VOID ASMCFUNC int21_syscall(iregs FAR * irp) } } +#ifdef WITHFAT32 + /* DOS 7.0+ FAT32 extended functions */ +int int21_fat32(lregs *r) +{ + COUNT rc; + + switch (r->AL) + { + /* Get extended drive parameter block */ + case 0x02: + { + struct dpb FAR *dpb; + struct xdpbdata FAR *xddp; + + if (r->CX < sizeof(struct xdpbdata)) + return DE_INVLDBUF; + + dpb = GetDriveDPB(r->DL, &rc); + if (rc != SUCCESS) + return rc; + + /* hazard: no error checking! */ + flush_buffers(dpb->dpb_unit); + dpb->dpb_flags = M_CHANGED; /* force reread of drive BPB/DPB */ + + if (media_check(dpb) < 0) + return DE_INVLDDRV; + + xddp = MK_FP(r->ES, r->DI); + + fmemcpy(&xddp->xdd_dpb, dpb, sizeof(struct dpb)); + xddp->xdd_dpbsize = sizeof(struct dpb); + break; + } + /* Get extended free drive space */ + case 0x03: + { + struct xfreespace FAR *xfsp = MK_FP(r->ES, r->DI); + + if (r->CX < sizeof(struct xfreespace)) + return DE_INVLDBUF; + + rc = DosGetExtFree(MK_FP(r->DS, r->DX), xfsp); + if (rc != SUCCESS) + return rc; + xfsp->xfs_datasize = sizeof(struct xfreespace); + xfsp->xfs_version.actual = 0; + break; + } + /* Set DPB to use for formatting */ + case 0x04: + { + struct xdpbforformat FAR *xdffp = MK_FP(r->ES, r->DI); + struct dpb FAR *dpb; + if (r->CX < sizeof(struct xdpbforformat)) + { + return DE_INVLDBUF; + } + dpb = GetDriveDPB(r->DL, &rc); + if (rc != SUCCESS) + return rc; + + xdffp->xdff_datasize = sizeof(struct xdpbforformat); + xdffp->xdff_version.actual = 0; + + switch ((UWORD) xdffp->xdff_function) + { + case 0x00: + { + DWORD nfreeclst = xdffp->xdff_f.setdpbcounts.nfreeclst; + DWORD cluster = xdffp->xdff_f.setdpbcounts.cluster; + if (ISFAT32(dpb)) + { + if ((dpb->dpb_xfsinfosec == 0xffff + && (nfreeclst != 0 || cluster != 0)) + || nfreeclst == 1 || nfreeclst > dpb->dpb_xsize + || cluster == 1 || cluster > dpb->dpb_xsize) + { + return DE_INVLDPARM; + } + dpb->dpb_xnfreeclst = nfreeclst; + dpb->dpb_xcluster = cluster; + write_fsinfo(dpb); + } + else + { + if (nfreeclst == 1 || nfreeclst > dpb->dpb_size || + cluster == 1 || cluster > dpb->dpb_size) + { + return DE_INVLDPARM; + } + dpb->dpb_nfreeclst = nfreeclst; + dpb->dpb_cluster = cluster; + } + break; + } + case 0x01: + { + ddt *pddt = getddt(r->DL); + fmemcpy(&pddt->ddt_bpb, xdffp->xdff_f.rebuilddpb.bpbp, + sizeof(bpb)); + } + case 0x02: + { + rebuild_dpb: + /* hazard: no error checking! */ + flush_buffers(dpb->dpb_unit); + dpb->dpb_flags = M_CHANGED; + + if (media_check(dpb) < 0) + return DE_INVLDDRV; + break; + } + case 0x03: + { + struct buffer FAR *bp; + bpb FAR *bpbp; + DWORD newmirroring = + xdffp->xdff_f.setmirroring.newmirroring; + + if (newmirroring != -1 + && (ISFAT32(dpb) + && (newmirroring & ~(0xf | 0x80)))) + { + return DE_INVLDPARM; + } + xdffp->xdff_f.setmirroring.oldmirroring = + (ISFAT32(dpb) ? dpb->dpb_xflags : 0); + if (newmirroring != -1 && ISFAT32(dpb)) + { + bp = getblock(1, dpb->dpb_unit); + bp->b_flag &= ~(BFR_DATA | BFR_DIR | BFR_FAT); + bp->b_flag |= BFR_VALID | BFR_DIRTY; + bpbp = (bpb FAR *) & bp->b_buffer[BT_BPB]; + bpbp->bpb_xflags = newmirroring; + } + goto rebuild_dpb; + } + case 0x04: + { + struct buffer FAR *bp; + bpb FAR *bpbp; + DWORD rootclst = xdffp->xdff_f.setroot.newrootclst; + if (!ISFAT32(dpb) + || (rootclst != -1 + && (rootclst == 1 + || rootclst > dpb->dpb_xsize))) + { + return DE_INVLDPARM; + } + xdffp->xdff_f.setroot.oldrootclst = dpb->dpb_xrootclst; + if (rootclst != -1) + { + bp = getblock(1, dpb->dpb_unit); + bp->b_flag &= ~(BFR_DATA | BFR_DIR | BFR_FAT); + bp->b_flag |= BFR_VALID | BFR_DIRTY; + bpbp = (bpb FAR *) & bp->b_buffer[BT_BPB]; + bpbp->bpb_xrootclst = rootclst; + } + goto rebuild_dpb; + } + } + + break; + } + /* Extended absolute disk read/write */ + /* TODO(vlp) consider using of the 13-14th bits of SI */ + case 0x05: + { + struct HugeSectorBlock FAR *SectorBlock = + (struct HugeSectorBlock FAR *)MK_FP(r->DS, r->BX); + UBYTE mode; + + if (r->CX != 0xffff || ((r->SI & 1) == 0 && r->SI != 0) + || (r->SI & ~0x6001)) + { + return DE_INVLDPARM; + } + + if (r->DL - 1 >= lastdrive || r->DL == 0) + return -0x207; + + if (r->SI == 0) + mode = DSKREADINT25; + else + mode = DSKWRITEINT26; + + r->AX = + dskxfer(r->DL - 1, SectorBlock->blkno, SectorBlock->buf, + SectorBlock->nblks, mode); + + if (mode == DSKWRITEINT26) + if (r->AX <= 0) + setinvld(r->DL - 1); + + if (r->AX > 0) + return -0x20c; + break; + } + default: + return DE_INVLDFUNC; + } + return SUCCESS; +} +#endif + VOID ASMCFUNC int21_service(iregs FAR * r) { COUNT rc = 0; - void FAR *FP_DS_DX = MK_FP(r->DS, r->DX); /* this is saved so often, - that this saves ~100 bytes */ + lregs lr; /* 8 local registers (ax, bx, cx, dx, si, di, ds, es) */ + +#define FP_DS_DX (MK_FP(lr.DS, lr.DX)) +#define FP_ES_DI (MK_FP(lr.ES, lr.DI)) + #define CLEAR_CARRY_FLAG() r->FLAGS &= ~FLG_CARRY #define SET_CARRY_FLAG() r->FLAGS |= FLG_CARRY ((psp FAR *) MK_FP(cu_psp, 0))->ps_stack = (BYTE FAR *) r; + lr.AX = r->AX; + lr.BX = r->BX; + lr.CX = r->CX; + lr.DX = r->DX; + lr.SI = r->SI; + lr.DI = r->DI; + lr.DS = r->DS; + lr.ES = r->ES; + +dispatch: + #ifdef DEBUG if (bDumpRegs) { @@ -177,14 +394,13 @@ VOID ASMCFUNC int21_service(iregs FAR * r) } #endif - if (r->AH >= 0x38 && r->AH <= 0x4F) + if ((lr.AH >= 0x38 && lr.AH <= 0x4F) || (lr.AH >= 0x56 && lr.AH <= 0x5c)) CLEAR_CARRY_FLAG(); /* Clear carry by default for these functions */ -dispatch: /* Check for Ctrl-Break */ - switch (r->AH) + switch (lr.AH) { default: if (!break_ena) @@ -203,94 +419,78 @@ dispatch: } /* The dispatch handler */ - switch (r->AH) + switch (lr.AH) { /* int 21h common error handler */ case 0x64: - error_invalid: - r->AX = -DE_INVLDFUNC; - goto error_out; - error_exit: - r->AX = -rc; - error_out: - CritErrCode = r->AX; /* Maybe set */ - SET_CARRY_FLAG(); - break; + goto error_invalid; /* case 0x00: --> Simulate a DOS-4C-00 */ /* Read Keyboard with Echo */ case 0x01: - r->AL = _sti(TRUE); - sto(r->AL); + lr.AL = _sti(TRUE); + sto(lr.AL); break; /* Display Character */ case 0x02: - sto(r->DL); + sto(lr.DL); break; /* Auxiliary Input */ case 0x03: - { - COUNT scratch; - GenericRead(STDAUX, 1, (BYTE FAR *) & r->AL, - (COUNT FAR *) & scratch, TRUE); - break; - } + BinaryRead(STDAUX, &lr.AL, &UnusedRetVal); + break; /* Auxiliary Output */ case 0x04: - { - COUNT scratch; - DosWrite(STDAUX, 1, (BYTE FAR *) & r->DL, (COUNT FAR *) & scratch); - break; - } + DosWrite(STDAUX, 1, (BYTE FAR *) & lr.DL, & UnusedRetVal); + break; /* Print Character */ case 0x05: - { - COUNT scratch; - DosWrite(STDPRN, 1, (BYTE FAR *) & r->DL, (COUNT FAR *) & scratch); - break; - } + DosWrite(STDPRN, 1, (BYTE FAR *) & lr.DL, & UnusedRetVal); + break; /* Direct Console I/O */ case 0x06: - if (r->DL != 0xff) - sto(r->DL); + if (lr.DL != 0xff) + sto(lr.DL); else if (StdinBusy()) { - r->AL = 0x00; + lr.AL = 0x00; r->FLAGS |= FLG_ZERO; } else { r->FLAGS &= ~FLG_ZERO; - r->AL = _sti(FALSE); + lr.AL = _sti(FALSE); } break; /* Direct Console Input */ case 0x07: - r->AL = _sti(FALSE); + lr.AL = _sti(FALSE); break; /* Read Keyboard Without Echo */ case 0x08: - r->AL = _sti(TRUE); + lr.AL = _sti(TRUE); break; /* Display String */ case 0x09: - { - BYTE FAR *q; - q = FP_DS_DX; - while (*q != '$') - ++q; - DosWrite(STDOUT, FP_OFF(q) - FP_OFF(FP_DS_DX), FP_DS_DX, - (COUNT FAR *) & UnusedRetVal); + { + unsigned count; + + for (count = 0; ; count++) + if (((UBYTE FAR *)FP_DS_DX)[count] == '$') + break; + + DosWrite(STDOUT, count, FP_DS_DX, + & UnusedRetVal); } - r->AL = '$'; + lr.AL = '$'; break; /* Buffered Keyboard Input */ @@ -301,26 +501,26 @@ dispatch: /* Check Stdin Status */ case 0x0b: if (StdinBusy()) - r->AL = 0x00; + lr.AL = 0x00; else - r->AL = 0xFF; + lr.AL = 0xFF; break; /* Flush Buffer, Read Keayboard */ case 0x0c: KbdFlush(); - switch (r->AL) + switch (lr.AL) { case 0x01: case 0x06: case 0x07: case 0x08: case 0x0a: - r->AH = r->AL; + lr.AH = lr.AL; goto dispatch; default: - r->AL = 0x00; + lr.AL = 0x00; break; } break; @@ -332,79 +532,50 @@ dispatch: /* Set Default Drive */ case 0x0e: - r->AL = DosSelectDrv(r->DL); + lr.AL = DosSelectDrv(lr.DL); break; case 0x0f: - if (FcbOpen(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbOpen(FP_DS_DX, O_FCB | O_LEGACY | O_OPEN | O_RDWR); break; case 0x10: - if (FcbClose(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbClose(FP_DS_DX); break; case 0x11: - if (FcbFindFirst(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbFindFirstNext(FP_DS_DX, TRUE); break; case 0x12: - if (FcbFindNext(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbFindFirstNext(FP_DS_DX, FALSE); break; case 0x13: - if (FcbDelete(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbDelete(FP_DS_DX); break; case 0x14: - { - if (FcbRead(FP_DS_DX, &CritErrCode, 0)) - r->AL = 0; - else - r->AL = CritErrCode; - break; - } + /* FCB read */ + lr.AL = FcbReadWrite(FP_DS_DX, 0, XFR_READ); + break; case 0x15: - { - if (FcbWrite(FP_DS_DX, &CritErrCode, 0)) - r->AL = 0; - else - r->AL = CritErrCode; - break; - } + /* FCB write */ + lr.AL = FcbReadWrite(FP_DS_DX, 0, XFR_WRITE); + break; case 0x16: - if (FcbCreate(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbOpen(FP_DS_DX, O_FCB | O_LEGACY | O_CREAT | O_TRUNC | O_RDWR); break; case 0x17: - if (FcbRename(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbRename(FP_DS_DX); break; default: #ifdef DEBUG - printf("Unsupported INT21 AH = 0x%x, AL = 0x%x.\n", r->AH, r->AL); + printf("Unsupported INT21 AH = 0x%x, AL = 0x%x.\n", lr.AH, lr.AL); #endif /* Fall through. */ @@ -417,12 +588,12 @@ dispatch: case 0x61: #endif case 0x6b: - r->AL = 0; + lr.AL = 0; break; /* Get Default Drive */ case 0x19: - r->AL = default_drive; + lr.AL = default_drive; break; /* Set DTA */ @@ -437,29 +608,20 @@ dispatch: /* Get Default Drive Data */ case 0x1b: - { - BYTE FAR *p; - - FatGetDrvData(0, - (UCOUNT FAR *) & r->AX, - (UCOUNT FAR *) & r->CX, - (UCOUNT FAR *) & r->DX, (BYTE FAR **) & p); - r->DS = FP_SEG(p); - r->BX = FP_OFF(p); - } - break; + lr.DL = 0; + /* fall through */ /* Get Drive Data */ case 0x1c: { BYTE FAR *p; - FatGetDrvData(r->DL, - (UCOUNT FAR *) & r->AX, - (UCOUNT FAR *) & r->CX, - (UCOUNT FAR *) & r->DX, (BYTE FAR **) & p); - r->DS = FP_SEG(p); - r->BX = FP_OFF(p); + p = FatGetDrvData(lr.DL, &lr.AX, &lr.CX, &lr.DX); + lr.DS = FP_SEG(p); + lr.BX = FP_OFF(p); + lr.CX = lr.CX; + lr.DX = lr.DX; + lr.AX = lr.AX; } break; @@ -468,30 +630,17 @@ dispatch: /* Random read using FCB */ case 0x21: - { - if (FcbRandomIO(FP_DS_DX, &CritErrCode, FcbRead)) - r->AL = 0; - else - r->AL = CritErrCode; - break; - } + lr.AL = FcbRandomIO(FP_DS_DX, XFR_READ); + break; /* Random write using FCB */ case 0x22: - { - if (FcbRandomIO(FP_DS_DX, &CritErrCode, FcbWrite)) - r->AL = 0; - else - r->AL = CritErrCode; - break; - } + lr.AL = FcbRandomIO(FP_DS_DX, XFR_WRITE); + break; /* Get file size in records using FCB */ case 0x23: - if (FcbGetFileSize(FP_DS_DX)) - r->AL = 0; - else - r->AL = 0xff; + lr.AL = FcbGetFileSize(FP_DS_DX); break; /* Set random record field in FCB */ @@ -501,7 +650,7 @@ dispatch: /* Set Interrupt Vector */ case 0x25: - setvec(r->AL, FP_DS_DX); + setvec(lr.AL, FP_DS_DX); break; /* Dos Create New Psp */ @@ -509,92 +658,81 @@ dispatch: { psp FAR *p = MK_FP(cu_psp, 0); - new_psp((psp FAR *) MK_FP(r->DX, 0), p->ps_size); + new_psp((psp FAR *) MK_FP(lr.DX, 0), p->ps_size); } break; /* Read random record(s) using FCB */ case 0x27: - { - if (FcbRandomBlockRead(FP_DS_DX, r->CX, &CritErrCode)) - r->AL = 0; - else - r->AL = CritErrCode; - break; - } + lr.AL = FcbRandomBlockIO(FP_DS_DX, lr.CX, XFR_READ); + break; /* Write random record(s) using FCB */ case 0x28: - { - if (FcbRandomBlockWrite(FP_DS_DX, r->CX, &CritErrCode)) - r->AL = 0; - else - r->AL = CritErrCode; - break; - } + lr.AL = FcbRandomBlockIO(FP_DS_DX, lr.CX, XFR_WRITE); + break; /* Parse File Name */ case 0x29: { - const BYTE FAR *lpFileName = MK_FP(r->DS, r->SI); - r->AL = FcbParseFname(r->AL, &lpFileName, MK_FP(r->ES, r->DI)); - r->DS = FP_SEG(lpFileName); - r->SI = FP_OFF(lpFileName); + UWORD offset = FcbParseFname(&rc, MK_FP(lr.DS, lr.SI), FP_ES_DI); + lr.AL = rc; + lr.SI += offset; } break; /* Get Date */ case 0x2a: - DosGetDate((BYTE FAR *) & (r->AL), /* WeekDay */ - (BYTE FAR *) & (r->DH), /* Month */ - (BYTE FAR *) & (r->DL), /* MonthDay */ - (COUNT FAR *) & (r->CX)); /* Year */ + DosGetDate(&lr.AL, /* WeekDay */ + &lr.DH, /* Month */ + &lr.DL, /* MonthDay */ + &lr.CX); /* Year */ break; /* Set Date */ case 0x2b: - rc = DosSetDate(r->DH, /* Month */ - r->DL, /* MonthDay */ - r->CX); /* Year */ - r->AL = (rc != SUCCESS ? 0xff : 0); + rc = DosSetDate(lr.DH, /* Month */ + lr.DL, /* MonthDay */ + lr.CX); /* Year */ + lr.AL = (rc != SUCCESS ? 0xff : 0); break; /* Get Time */ case 0x2c: - DosGetTime((BYTE FAR *) & (r->CH), /* Hour */ - (BYTE FAR *) & (r->CL), /* Minutes */ - (BYTE FAR *) & (r->DH), /* Seconds */ - (BYTE FAR *) & (r->DL)); /* Hundredths */ + DosGetTime(&lr.CH, /* Hour */ + &lr.CL, /* Minutes */ + &lr.DH, /* Seconds */ + &lr.DL); /* Hundredths */ break; /* Set Date */ case 0x2d: - rc = DosSetTime(r->CH, /* Hour */ - r->CL, /* Minutes */ - r->DH, /* Seconds */ - r->DL); /* Hundredths */ - r->AL = (rc != SUCCESS ? 0xff : 0); + rc = DosSetTime(lr.CH, /* Hour */ + lr.CL, /* Minutes */ + lr.DH, /* Seconds */ + lr.DL); /* Hundredths */ + lr.AL = (rc != SUCCESS ? 0xff : 0); break; /* Set verify flag */ case 0x2e: - verify_ena = (r->AL ? TRUE : FALSE); + verify_ena = (lr.AL ? TRUE : FALSE); break; /* Get DTA */ case 0x2f: - r->ES = FP_SEG(dta); - r->BX = FP_OFF(dta); + lr.ES = FP_SEG(dta); + lr.BX = FP_OFF(dta); break; /* Get DOS Version */ case 0x30: - r->AL = os_major; - r->AH = os_minor; - r->BH = OEM_ID; - r->CH = REVISION_MAJOR; /* JPP */ - r->CL = REVISION_MINOR; - r->BL = REVISION_SEQ; + lr.AL = os_major; + lr.AH = os_minor; + lr.BH = OEM_ID; + lr.CH = REVISION_MAJOR; /* JPP */ + lr.CL = REVISION_MINOR; + lr.BL = REVISION_SEQ; if (ReturnAnyDosVersionExpected) { @@ -609,15 +747,15 @@ dispatch: if (retp[0] == 0x3d && /* cmp ax, xxyy */ (retp[3] == 0x75 || retp[3] == 0x74)) /* je/jne error */ { - r->AL = retp[1]; - r->AH = retp[2]; + lr.AL = retp[1]; + lr.AH = retp[2]; } else if (retp[0] == 0x86 && /* xchg al,ah */ retp[1] == 0xc4 && retp[2] == 0x3d && /* cmp ax, xxyy */ (retp[5] == 0x75 || retp[5] == 0x74)) /* je/jne error */ { - r->AL = retp[4]; - r->AH = retp[3]; + lr.AL = retp[4]; + lr.AH = retp[3]; } } @@ -626,9 +764,9 @@ dispatch: /* Keep Program (Terminate and stay resident) */ case 0x31: - DosMemChange(cu_psp, r->DX < 6 ? 6 : r->DX, 0); + DosMemChange(cu_psp, lr.DX < 6 ? 6 : lr.DX, 0); return_mode = 3; - return_code = r->AL; + return_code = lr.AL; tsr = TRUE; return_user(); break; @@ -641,16 +779,16 @@ dispatch: /* INT21/32 is documented to reread the DPB */ { struct dpb FAR *dpb; - UCOUNT drv = r->DL; + UCOUNT drv = lr.DL; - if (drv == 0 || r->AH == 0x1f) + if (drv == 0 || lr.AH == 0x1f) drv = default_drive; else drv--; if (drv >= lastdrive) { - r->AL = 0xFF; + lr.AL = 0xFF; CritErrCode = 0x0f; break; } @@ -658,10 +796,11 @@ dispatch: dpb = CDSp[drv].cdsDpb; if (dpb == 0 || CDSp[drv].cdsFlags & CDSNETWDRV) { - r->AL = 0xFF; + lr.AL = 0xFF; CritErrCode = 0x0f; break; } + /* hazard: no error checking! */ flush_buffers(dpb->dpb_unit); dpb->dpb_flags = M_CHANGED; /* force flush and reread of drive BPB/DPB */ @@ -671,13 +810,13 @@ dispatch: if (media_check(dpb) < 0) #endif { - r->AL = 0xff; + lr.AL = 0xff; CritErrCode = 0x0f; break; } - r->DS = FP_SEG(dpb); - r->BX = FP_OFF(dpb); - r->AL = 0; + lr.DS = FP_SEG(dpb); + lr.BX = FP_OFF(dpb); + lr.AL = 0; } break; @@ -687,46 +826,38 @@ dispatch: */ /* Get InDOS flag */ case 0x34: - { - BYTE FAR *p; - - p = (BYTE FAR *) ((BYTE *) & InDOS); - r->ES = FP_SEG(p); - r->BX = FP_OFF(p); - } + lr.ES = FP_SEG(&InDOS); + lr.BX = FP_OFF(&InDOS); break; /* Get Interrupt Vector */ - case 0x35: - { - intvec p = getvec((COUNT) r->AL); - r->ES = FP_SEG(p); - r->BX = FP_OFF(p); + case 0x35: + { + intvec p = getvec((COUNT) lr.AL); + lr.ES = FP_SEG(p); + lr.BX = FP_OFF(p); } break; /* Dos Get Disk Free Space */ case 0x36: - DosGetFree(r->DL, - (UCOUNT FAR *) & r->AX, - (UCOUNT FAR *) & r->BX, - (UCOUNT FAR *) & r->CX, (UCOUNT FAR *) & r->DX); + DosGetFree(lr.DL, &lr.AX, &lr.BX, &lr.CX, &lr.DX); break; /* Undocumented Get/Set Switchar */ case 0x37: - switch (r->AL) + switch (lr.AL) { /* Get switch character */ case 0x00: - r->DL = switchar; - r->AL = 0x00; + lr.DL = switchar; + lr.AL = 0x00; break; /* Set switch character */ case 0x01: - switchar = r->DL; - r->AL = 0x00; + switchar = lr.DL; + lr.AL = 0x00; break; default: @@ -737,14 +868,14 @@ dispatch: /* Get/Set Country Info */ case 0x38: { - UWORD cntry = r->AL; + UWORD cntry = lr.AL; if (cntry == 0) cntry = (UWORD) - 1; else if (cntry == 0xff) - cntry = r->BX; + cntry = lr.BX; - if (0xffff == r->DX) + if (0xffff == lr.DX) { /* Set Country Code */ if ((rc = DosSetCountry(cntry)) < 0) @@ -759,7 +890,7 @@ dispatch: if (cntry == (UWORD) - 1) cntry = 1; /* END OF HACK */ - r->AX = r->BX = cntry; + lr.AX = lr.BX = cntry; } } break; @@ -786,36 +917,48 @@ dispatch: /* Dos Create File */ case 0x3c: - if ((rc = DosCreat(FP_DS_DX, r->CX)) < 0) - goto error_exit; - else - r->AX = rc; - break; + { + long lrc = DosOpen(FP_DS_DX, O_LEGACY | O_RDWR | O_CREAT | O_TRUNC, lr.CL); + + if (lrc < 0) + { + rc = (COUNT)lrc; + goto error_exit; + } + lr.AX = (UWORD)lrc; + break; + } /* Dos Open */ case 0x3d: - if ((rc = DosOpen(FP_DS_DX, r->AL)) < 0) - goto error_exit; - else - r->AX = rc; - break; + { + long lrc = DosOpen(FP_DS_DX, O_LEGACY | O_OPEN | lr.AL, 0); + + if (lrc < 0) + { + rc = (COUNT)lrc; + goto error_exit; + } + lr.AX = (UWORD)lrc; + break; + } /* Dos Close */ case 0x3e: - if ((rc = DosClose(r->BX)) < 0) + if ((rc = DosClose(lr.BX)) < 0) goto error_exit; break; /* Dos Read */ case 0x3f: - r->AX = DosRead(r->BX, r->CX, FP_DS_DX, (COUNT FAR *) & rc); + lr.AX = DosRead(lr.BX, lr.CX, FP_DS_DX, & rc); if (rc != SUCCESS) goto error_exit; break; /* Dos Write */ case 0x40: - r->AX = DosWrite(r->BX, r->CX, FP_DS_DX, (COUNT FAR *) & rc); + lr.AX = DosWrite(lr.BX, lr.CX, FP_DS_DX, & rc); if (rc != SUCCESS) goto error_exit; break; @@ -831,30 +974,34 @@ dispatch: case 0x42: { ULONG lrc; - if ((rc = - DosSeek(r->BX, (LONG) ((((LONG) (r->CX)) << 16) | r->DX), - r->AL, &lrc)) < 0) + if (lr.AL > 2) + goto error_invalid; + lrc = DosSeek(lr.BX, (LONG)((((ULONG) (lr.CX)) << 16) | lr.DX), lr.AL); + if (lrc == (ULONG)-1) + { + rc = -DE_INVLDHNDL; goto error_exit; + } else { - r->DX = (lrc >> 16); - r->AX = (UWORD) lrc; + lr.DX = (lrc >> 16); + lr.AX = (UWORD) lrc; } } break; /* Get/Set File Attributes */ case 0x43: - switch (r->AL) + switch (lr.AL) { case 0x00: rc = DosGetFattr((BYTE FAR *) FP_DS_DX); if (rc >= SUCCESS) - r->CX = rc; + lr.CX = rc; break; case 0x01: - rc = DosSetFattr((BYTE FAR *) FP_DS_DX, r->CX); + rc = DosSetFattr((BYTE FAR *) FP_DS_DX, lr.CX); break; default: @@ -866,96 +1013,92 @@ dispatch: /* Device I/O Control */ case 0x44: - rc = DosDevIOctl(r); /* can set critical error code! */ + rc = DosDevIOctl(&lr); /* can set critical error code! */ if (rc != SUCCESS) { - r->AX = -rc; + lr.AX = -rc; if (rc != DE_DEVICE && rc != DE_ACCESS) CritErrCode = -rc; - SET_CARRY_FLAG(); + goto error_carry; } break; /* Duplicate File Handle */ case 0x45: - rc = DosDup(r->BX); - if (rc < SUCCESS) - goto error_exit; - else - r->AX = rc; + { + long lrc = DosDup(lr.BX); + if (lrc < SUCCESS) + { + rc = (COUNT)lrc; + goto error_exit; + } + lr.AX = (UWORD)lrc; + } break; /* Force Duplicate File Handle */ case 0x46: - rc = DosForceDup(r->BX, r->CX); + rc = DosForceDup(lr.BX, lr.CX); if (rc < SUCCESS) goto error_exit; break; /* Get Current Directory */ case 0x47: - if ((rc = DosGetCuDir(r->DL, MK_FP(r->DS, r->SI))) < 0) + if ((rc = DosGetCuDir(lr.DL, MK_FP(lr.DS, lr.SI))) < 0) goto error_exit; else - r->AX = 0x0100; /*jpp: from interrupt list */ + lr.AX = 0x0100; /*jpp: from interrupt list */ break; /* Allocate memory */ case 0x48: if ((rc = - DosMemAlloc(r->BX, mem_access_mode, &(r->AX), &(r->BX))) < 0) + DosMemAlloc(lr.BX, mem_access_mode, &(lr.AX), &(lr.BX))) < 0) { - DosMemLargest(&(r->BX)); + DosMemLargest(&(lr.BX)); goto error_exit; } else - ++(r->AX); /* DosMemAlloc() returns seg of MCB rather than data */ + ++(lr.AX); /* DosMemAlloc() returns seg of MCB rather than data */ break; /* Free memory */ case 0x49: - if ((rc = DosMemFree((r->ES) - 1)) < 0) + if ((rc = DosMemFree((lr.ES) - 1)) < 0) goto error_exit; break; /* Set memory block size */ case 0x4a: + if ((rc = DosMemChange(lr.ES, lr.BX, &lr.BX)) < 0) { - UWORD maxSize; - - if ((rc = DosMemChange(r->ES, r->BX, &maxSize)) < 0) - { - if (rc == DE_NOMEM) - r->BX = maxSize; - #if 0 - if (cu_psp == r->ES) - { + if (cu_psp == lr.ES) + { - psp FAR *p; - - p = MK_FP(cu_psp, 0); - p->ps_size = r->BX + cu_psp; - } -#endif - goto error_exit; + psp FAR *p; + + p = MK_FP(cu_psp, 0); + p->ps_size = lr.BX + cu_psp; } - - break; +#endif + goto error_exit; } + break; /* Load and Execute Program */ case 0x4b: break_flg = FALSE; - if ((rc = DosExec(r->AL, MK_FP(r->ES, r->BX), FP_DS_DX)) != SUCCESS) + if ((rc = DosExec(lr.AL, MK_FP(lr.ES, lr.BX), FP_DS_DX)) != SUCCESS) goto error_exit; break; /* Terminate Program */ case 0x00: - r->AX = 0x4c00; + lr.AX = 0x4c00; /* End Program */ case 0x4c: @@ -977,7 +1120,7 @@ dispatch: { return_mode = 0; } - return_code = r->AL; + return_code = lr.AL; if (DosMemCheck() != SUCCESS) panic("MCB chain corrupted"); #ifdef TSC @@ -988,17 +1131,17 @@ dispatch: /* Get Child-program Return Value */ case 0x4d: - r->AL = return_code; - r->AH = return_mode; + lr.AL = return_code; + lr.AH = return_mode; break; /* Dos Find First */ case 0x4e: /* dta for this call is set on entry. This */ /* needs to be changed for new versions. */ - if ((rc = DosFindFirst((UCOUNT) r->CX, (BYTE FAR *) FP_DS_DX)) < 0) + if ((rc = DosFindFirst((UCOUNT) lr.CX, (BYTE FAR *) FP_DS_DX)) < 0) goto error_exit; - r->AX = 0; + lr.AX = 0; break; /* Dos Find Next */ @@ -1007,7 +1150,7 @@ dispatch: /* needs to be changed for new versions. */ if ((rc = DosFindNext()) < 0) goto error_exit; - r->AX = -SUCCESS; + lr.AX = -SUCCESS; break; /* case 0x50: @@ -1017,64 +1160,56 @@ dispatch: /* ************UNDOCUMENTED************************************* */ /* Get List of Lists */ case 0x52: - { - BYTE FAR *p; - - p = (BYTE FAR *) & DPBp; - r->ES = FP_SEG(p); - r->BX = FP_OFF(p); - } + lr.ES = FP_SEG(&DPBp); + lr.BX = FP_OFF(&DPBp); break; case 0x53: /* DOS 2+ internal - TRANSLATE BIOS PARAMETER BLOCK TO DRIVE PARAM BLOCK */ - bpb_to_dpb((bpb FAR *) MK_FP(r->DS, r->SI), - (struct dpb FAR *)MK_FP(r->ES, r->BP) + bpb_to_dpb((bpb FAR *) MK_FP(lr.DS, lr.SI), + (struct dpb FAR *)MK_FP(lr.ES, r->BP) #ifdef WITHFAT32 - , (r->CX == 0x4558 && r->DX == 0x4152) + , (lr.CX == 0x4558 && lr.DX == 0x4152) #endif ); break; /* Get verify state */ case 0x54: - r->AL = (verify_ena ? TRUE : FALSE); + lr.AL = (verify_ena ? TRUE : FALSE); break; /* ************UNDOCUMENTED************************************* */ /* Dos Create New Psp & set p_size */ case 0x55: - new_psp((psp FAR *) MK_FP(r->DX, 0), r->SI); - cu_psp = r->DX; + new_psp((psp FAR *) MK_FP(lr.DX, 0), lr.SI); + cu_psp = lr.DX; break; /* Dos Rename */ case 0x56: rc = DosRename((BYTE FAR *) FP_DS_DX, - (BYTE FAR *) MK_FP(r->ES, r->DI)); + (BYTE FAR *) FP_ES_DI); if (rc < SUCCESS) goto error_exit; - else - CLEAR_CARRY_FLAG(); break; /* Get/Set File Date and Time */ case 0x57: - CLEAR_CARRY_FLAG(); - switch (r->AL) + switch (lr.AL) { case 0x00: - rc = DosGetFtime((COUNT) r->BX, /* Handle */ - (date FAR *) & r->DX, /* FileDate */ - (time FAR *) & r->CX); /* FileTime */ + rc = DosGetFtime((COUNT) lr.BX, /* Handle */ + &lr.DX, /* FileDate */ + &lr.CX); /* FileTime */ if (rc < SUCCESS) goto error_exit; break; case 0x01: - rc = DosSetFtime((COUNT) r->BX, /* Handle */ - (date) r->DX, /* FileDate */ - (time) r->CX); /* FileTime */ + rc = DosSetFtime((COUNT) lr.BX, /* Handle */ + (date) lr.DX, /* FileDate */ + (time) lr.CX); /* FileTime */ if (rc < SUCCESS) goto error_exit; break; @@ -1086,17 +1221,16 @@ dispatch: /* Get/Set Allocation Strategy */ case 0x58: - CLEAR_CARRY_FLAG(); - switch (r->AL) + switch (lr.AL) { case 0x00: - r->AL = mem_access_mode; - r->AH = 0; + lr.AL = mem_access_mode; + lr.AH = 0; break; case 0x01: { - switch (r->BL) + switch (lr.BL) { case LAST_FIT: case LAST_FIT_U: @@ -1107,7 +1241,7 @@ dispatch: case FIRST_FIT: case FIRST_FIT_U: case FIRST_FIT_UO: - mem_access_mode = r->BL; + mem_access_mode = lr.BL; break; default: @@ -1117,13 +1251,13 @@ dispatch: break; case 0x02: - r->AL = uppermem_link; + lr.AL = uppermem_link; break; case 0x03: if (uppermem_root != 0xffff) /* always error if not exists */ { - DosUmbLink(r->BL); + DosUmbLink(lr.BL); break; } /* else fall through */ @@ -1140,92 +1274,67 @@ dispatch: /* Get Extended Error */ case 0x59: - r->AX = CritErrCode; - r->ES = FP_SEG(CritErrDev); - r->DI = FP_OFF(CritErrDev); - r->CH = CritErrLocus; - r->BH = CritErrClass; - r->BL = CritErrAction; - CLEAR_CARRY_FLAG(); + lr.AX = CritErrCode; + lr.ES = FP_SEG(CritErrDev); + lr.DI = FP_OFF(CritErrDev); + lr.CH = CritErrLocus; + lr.BH = CritErrClass; + lr.BL = CritErrAction; break; /* Create Temporary File */ case 0x5a: - if ((rc = DosMkTmp(FP_DS_DX, r->CX)) < 0) + if ((rc = DosMkTmp(FP_DS_DX, lr.CX)) < 0) goto error_exit; - else - { - r->AX = rc; - CLEAR_CARRY_FLAG(); - } + lr.AX = rc; break; /* Create New File */ case 0x5b: - if (!IsDevice(FP_DS_DX) && (rc = DosOpen(FP_DS_DX, 0)) >= 0) { - DosClose(rc); - r->AX = 80; - goto error_out; - } - else - { - if ((rc = DosCreat(FP_DS_DX, r->CX)) < 0) - goto error_exit; - else + long lrc = DosOpen(FP_DS_DX, O_LEGACY | O_RDWR | O_CREAT, lr.CX); + if (lrc < 0) { - r->AX = rc; - CLEAR_CARRY_FLAG(); + rc = (COUNT)lrc; + goto error_exit; } + lr.AX = (UWORD)lrc; + break; } - break; /* /// Added for SHARE. - Ron Cemer */ /* Lock/unlock file access */ case 0x5c: if ((rc = DosLockUnlock - (r->BX, - (((unsigned long)r->CX) << 16) | (((unsigned long)r-> - DX) & 0xffffL), - (((unsigned long)r->SI) << 16) | (((unsigned long)r-> - DI) & 0xffffL), - ((r->AX & 0xff) != 0))) != 0) + (lr.BX, + (((unsigned long)lr.CX) << 16) | (((unsigned long)lr.DX) ), + (((unsigned long)lr.SI) << 16) | (((unsigned long)lr.DI) ), + ((lr.AX & 0xff) != 0))) != 0) goto error_exit; - CLEAR_CARRY_FLAG(); break; /* /// End of additions for SHARE. - Ron Cemer */ /* UNDOCUMENTED: server, share.exe and sda function */ case 0x5d: - switch (r->AL) + switch (lr.AL) { /* Remote Server Call */ case 0x00: - { - UWORD FAR *x = FP_DS_DX; - r->AX = x[0]; - r->BX = x[1]; - r->CX = x[2]; - r->DX = x[3]; - r->SI = x[4]; - r->DI = x[5]; - r->DS = x[6]; - r->ES = x[7]; - } + fmemcpy(&lr, FP_DS_DX, sizeof(lr)); goto dispatch; case 0x06: - r->DS = FP_SEG(internal_data); - r->SI = FP_OFF(internal_data); - r->CX = swap_indos - internal_data; - r->DX = swap_always - internal_data; + lr.DS = FP_SEG(internal_data); + lr.SI = FP_OFF(internal_data); + lr.CX = swap_indos - internal_data; + lr.DX = swap_always - internal_data; CLEAR_CARRY_FLAG(); break; case 0x07: case 0x08: case 0x09: - rc = remote_printredir(r->DX, Int21AX); + rc = remote_printredir(lr.DX, Int21AX); if (rc != SUCCESS) goto error_exit; CLEAR_CARRY_FLAG(); @@ -1237,41 +1346,41 @@ dispatch: case 0x5e: CLEAR_CARRY_FLAG(); - switch (r->AL) + switch (lr.AL) { case 0x00: - r->CX = get_machine_name(FP_DS_DX); + lr.CX = get_machine_name(FP_DS_DX); break; case 0x01: - set_machine_name(FP_DS_DX, r->CX); + set_machine_name(FP_DS_DX, lr.CX); break; default: - rc = remote_printset(r->BX, r->CX, r->DX, (MK_FP(r->ES, r->DI)), - r->SI, (MK_FP(r->DS, Int21AX))); + rc = remote_printset(lr.BX, lr.CX, lr.DX, (FP_ES_DI), + lr.SI, (MK_FP(lr.DS, Int21AX))); if (rc != SUCCESS) goto error_exit; - r->AX = SUCCESS; + lr.AX = SUCCESS; break; } break; case 0x5f: CLEAR_CARRY_FLAG(); - switch (r->AL) + switch (lr.AL) { case 0x07: - if (r->DL < lastdrive) + if (lr.DL < lastdrive) { - CDSp[r->DL].cdsFlags |= 0x100; + CDSp[lr.DL].cdsFlags |= 0x100; } break; case 0x08: - if (r->DL < lastdrive) + if (lr.DL < lastdrive) { - CDSp[r->DL].cdsFlags &= ~0x100; + CDSp[lr.DL].cdsFlags &= ~0x100; } break; @@ -1281,21 +1390,24 @@ dispatch: int_2f_111e_call(r); break;*/ - rc = remote_doredirect(r->BX, r->CX, r->DX, - (MK_FP(r->ES, r->DI)), r->SI, - (MK_FP(r->DS, Int21AX))); + rc = remote_doredirect(lr.BX, lr.CX, lr.DX, + (FP_ES_DI), lr.SI, + (MK_FP(lr.DS, Int21AX))); + /* the remote function manipulates *r directly !, + so we should not copy lr to r here */ if (rc != SUCCESS) - goto error_exit; - r->AX = SUCCESS; - break; + { + CritErrCode = -rc; /* Maybe set */ + SET_CARRY_FLAG(); + } + r->AX = -rc; + goto real_exit; } break; case 0x60: /* TRUENAME */ CLEAR_CARRY_FLAG(); - if ((rc = truename(MK_FP(r->DS, r->SI), - adjust_far(MK_FP(r->ES, r->DI)), - FALSE)) != SUCCESS) + if ((rc = DosTruename(MK_FP(lr.DS, lr.SI), adjust_far(FP_ES_DI))) < SUCCESS) goto error_exit; break; @@ -1305,7 +1417,7 @@ dispatch: /* DOS-C: tsc support */ case 0x61: #ifdef DEBUG - switch (r->AL) + switch (lr.AL) { case 0x01: bTraceNext = TRUE; @@ -1316,24 +1428,24 @@ dispatch: break; } #endif - r->AL = 0x00; + lr.AL = 0x00; break; #endif /* UNDOCUMENTED: return current psp case 0x62: is in int21_syscall - r->BX = cu_psp; + lr.BX = cu_psp; break; */ /* UNDOCUMENTED: Double byte and korean tables */ case 0x63: { - r->DS = FP_SEG(dbcsTable); - r->SI = FP_OFF(dbcsTable); + lr.DS = FP_SEG(&nlsDBCSHardcoded); + lr.SI = FP_OFF(&nlsDBCSHardcoded); #if 0 /* not really supported, but will pass. */ - r->AL = 0x00; /*jpp: according to interrupt list */ + lr.AL = 0x00; /*jpp: according to interrupt list */ /*Bart: fails for PQDI and WATCOM utilities: use the above again */ #endif @@ -1346,32 +1458,32 @@ dispatch: /* Extended country info */ case 0x65: - switch (r->AL) + switch (lr.AL) { case 0x20: /* upcase single character */ - r->DL = DosUpChar(r->DL); + lr.DL = DosUpChar(lr.DL); break; case 0x21: /* upcase memory area */ - DosUpMem(FP_DS_DX, r->CX); + DosUpMem(FP_DS_DX, lr.CX); break; case 0x22: /* upcase ASCIZ */ DosUpString(FP_DS_DX); break; case 0xA0: /* upcase single character of filenames */ - r->DL = DosUpFChar(r->DL); + lr.DL = DosUpFChar(lr.DL); break; case 0xA1: /* upcase memory area of filenames */ - DosUpFMem(FP_DS_DX, r->CX); + DosUpFMem(FP_DS_DX, lr.CX); break; case 0xA2: /* upcase ASCIZ of filenames */ DosUpFString(FP_DS_DX); break; case 0x23: /* check Yes/No response */ - r->AX = DosYesNo(r->DL); + lr.AX = DosYesNo(lr.DL); break; default: - if ((rc = DosGetData(r->AL, r->BX, r->DX, r->CX, - MK_FP(r->ES, r->DI))) < 0) + if ((rc = DosGetData(lr.AL, lr.BX, lr.DX, lr.CX, + FP_ES_DI)) < 0) { #ifdef NLS_DEBUG printf("DosGetData() := %d\n", rc); @@ -1389,15 +1501,14 @@ dispatch: /* Code Page functions */ case 0x66: - { - int rc; - switch (r->AL) + CLEAR_CARRY_FLAG(); + switch (lr.AL) { case 1: - rc = DosGetCodepage(&r->BX, &r->DX); + rc = DosGetCodepage(&lr.BX, &lr.DX); break; case 2: - rc = DosSetCodepage(r->BX, r->DX); + rc = DosSetCodepage(lr.BX, lr.DX); break; default: @@ -1405,59 +1516,55 @@ dispatch: } if (rc != SUCCESS) goto error_exit; - CLEAR_CARRY_FLAG(); break; - } /* Set Max file handle count */ case 0x67: - if ((rc = SetJFTSize(r->BX)) != SUCCESS) + CLEAR_CARRY_FLAG(); + if ((rc = SetJFTSize(lr.BX)) != SUCCESS) goto error_exit; - else - CLEAR_CARRY_FLAG(); break; /* Flush file buffer -- COMMIT FILE. */ case 0x68: case 0x6a: - if ((rc = DosCommit(r->BX)) < 0) + CLEAR_CARRY_FLAG(); + if ((rc = DosCommit(lr.BX)) < 0) goto error_exit; - else - CLEAR_CARRY_FLAG(); break; /* Get/Set Serial Number */ case 0x69: - rc = (r->BL == 0 ? default_drive : r->BL - 1); + CLEAR_CARRY_FLAG(); + rc = (lr.BL == 0 ? default_drive : lr.BL - 1); if (rc < lastdrive) { - UWORD saveCX = r->CX; + UWORD saveCX = lr.CX; if (CDSp[rc].cdsFlags & CDSNETWDRV) { goto error_invalid; } - switch (r->AL) + switch (lr.AL) { case 0x00: - r->AL = 0x0d; - r->CX = 0x0866; - rc = DosDevIOctl(r); + lr.AL = 0x0d; + lr.CX = 0x0866; + rc = DosDevIOctl(&lr); break; case 0x01: - r->AL = 0x0d; - r->CX = 0x0846; - rc = DosDevIOctl(r); + lr.AL = 0x0d; + lr.CX = 0x0846; + rc = DosDevIOctl(&lr); break; } - r->CX = saveCX; + lr.CX = saveCX; if (rc != SUCCESS) goto error_exit; - CLEAR_CARRY_FLAG(); break; } else - r->AL = 0xFF; + lr.AL = 0xFF; break; /* case 0x6a: see case 0x68 @@ -1466,285 +1573,46 @@ dispatch: /* Extended Open-Creat, not fully functional. (bits 4,5,6 of BH) */ case 0x6c: { - COUNT x = 0; - - if (r->AL != 0 || r->DH != 0 || - (r->DL & 0x0f) > 0x2 || (r->DL & 0xf0) > 0x10) - goto error_invalid; + long lrc; CLEAR_CARRY_FLAG(); - if ((rc = DosOpen(MK_FP(r->DS, r->SI), - (r->DL & 0x0f) == 0x1 ? r->BL : 0)) < 0) + + if (lr.AL != 0 || lr.DH != 0 || + (lr.DL & 0x0f) > 0x2 || (lr.DL & 0xf0) > 0x10) + goto error_invalid; + lrc = DosOpen(MK_FP(lr.DS, lr.SI), + (lr.BX & 0x7000) | ((lr.DL & 3) << 8) | + ((lr.DL & 0x10) << 6), lr.CL); + if (lrc < 0) { - if (r->DL < 0x10) - goto error_exit; - /* else try to create below */ + rc = (COUNT)lrc; + goto error_exit; } else - switch (r->DL & 0x0f) - { - case 0x0: - /* fail if file exists */ - DosClose(rc); - rc = DE_FILEEXISTS; - goto error_exit; - case 0x1: - /* file exists and opened: OK */ - r->CX = 0x01; - goto break_out; - case 0x2: - /* file exists: replace/open */ - DosClose(rc); - x = 1; - break; - } - /* cases 0x00, 0x01 are finished now */ - if ((rc = DosCreat(MK_FP(r->DS, r->SI), r->CX)) < 0) - goto error_exit; - - r->CX = x + 2; - break_out: - r->AX = rc; + { + lr.AX = (UWORD)lrc; + /* action */ + lr.CX = lrc >> 16; + } break; } /* case 0x6d and above not implemented : see default; return AL=0 */ #ifdef WITHFAT32 - /* DOS 7.0+ FAT32 extended funcitons */ + /* DOS 7.0+ FAT32 extended functions */ case 0x73: - { - switch (r->AL) - { - /* Get extended drive parameter block */ - case 0x02: - { - struct xdpbdata FAR *xddp = - (struct xdpbdata FAR *)MK_FP(r->ES, r->DI); - struct dpb FAR *dpb; - - if (r->CX < sizeof(struct xdpbdata)) - { - r->AX = -DE_INVLDBUF; - goto error_out; - } - - dpb = GetDriveDPB(r->DL, &rc); - if (rc != SUCCESS) - goto error_exit; - - flush_buffers(dpb->dpb_unit); - dpb->dpb_flags = M_CHANGED; /* force reread of drive BPB/DPB */ - - if (media_check(dpb) < 0) - { - r->AX = -DE_INVLDDRV; - goto error_out; - } - - fmemcpy(&xddp->xdd_dpb, dpb, sizeof(struct dpb)); - xddp->xdd_dpbsize = sizeof(struct dpb); - CLEAR_CARRY_FLAG(); - - break; - } - /* Get extended free drive space */ - case 0x03: - { - struct xfreespace FAR *xfsp = - (struct xfreespace FAR *)MK_FP(r->ES, r->DI); - if (r->CX < sizeof(struct xfreespace)) - { - r->AX = -DE_INVLDBUF; - goto error_out; - } - CLEAR_CARRY_FLAG(); - rc = DosGetExtFree((BYTE FAR *) FP_DS_DX, xfsp); - if (rc != SUCCESS) - goto error_exit; - xfsp->xfs_datasize = sizeof(struct xfreespace); - xfsp->xfs_version.actual = 0; - break; - } - /* Set DPB to use for formatting */ - case 0x04: - { - struct xdpbforformat FAR *xdffp = - (struct xdpbforformat FAR *)MK_FP(r->ES, r->DI); - struct dpb FAR *dpb; - if (r->CX < sizeof(struct xdpbforformat)) - { - r->AX = -DE_INVLDBUF; - goto error_out; - } - dpb = GetDriveDPB(r->DL, &rc); - if (rc != SUCCESS) - goto error_exit; - - CLEAR_CARRY_FLAG(); - xdffp->xdff_datasize = sizeof(struct xdpbforformat); - xdffp->xdff_version.actual = 0; - - switch ((UWORD) xdffp->xdff_function) - { - case 0x00: - { - DWORD nfreeclst = xdffp->xdff_f.setdpbcounts.nfreeclst; - DWORD cluster = xdffp->xdff_f.setdpbcounts.cluster; - if (ISFAT32(dpb)) - { - if ((dpb->dpb_xfsinfosec == 0xffff - && (nfreeclst != 0 || cluster != 0)) - || nfreeclst == 1 || nfreeclst > dpb->dpb_xsize - || cluster == 1 || cluster > dpb->dpb_xsize) - { - r->AX = -DE_INVLDPARM; - goto error_out; - } - dpb->dpb_xnfreeclst = nfreeclst; - dpb->dpb_xcluster = cluster; - write_fsinfo(dpb); - } - else - { - if (nfreeclst == 1 || nfreeclst > dpb->dpb_size || - cluster == 1 || cluster > dpb->dpb_size) - { - r->AX = -DE_INVLDPARM; - goto error_out; - } - dpb->dpb_nfreeclst = nfreeclst; - dpb->dpb_cluster = cluster; - } - break; - } - case 0x01: - { - ddt *pddt = getddt(r->DL); - fmemcpy(&pddt->ddt_bpb, xdffp->xdff_f.rebuilddpb.bpbp, - sizeof(bpb)); - } - case 0x02: - { - rebuild_dpb: - flush_buffers(dpb->dpb_unit); - dpb->dpb_flags = M_CHANGED; - - if (media_check(dpb) < 0) - { - r->AX = -DE_INVLDDRV; - goto error_out; - } - - break; - } - case 0x03: - { - struct buffer FAR *bp; - bpb FAR *bpbp; - DWORD newmirroring = - xdffp->xdff_f.setmirroring.newmirroring; - - if (newmirroring != -1 - && (ISFAT32(dpb) - && (newmirroring & ~(0xf | 0x80)))) - { - r->AX = -DE_INVLDPARM; - goto error_out; - } - xdffp->xdff_f.setmirroring.oldmirroring = - (ISFAT32(dpb) ? dpb->dpb_xflags : 0); - if (newmirroring != -1 && ISFAT32(dpb)) - { - bp = getblock(1, dpb->dpb_unit); - bp->b_flag &= ~(BFR_DATA | BFR_DIR | BFR_FAT); - bp->b_flag |= BFR_VALID | BFR_DIRTY; - bpbp = (bpb FAR *) & bp->b_buffer[BT_BPB]; - bpbp->bpb_xflags = newmirroring; - } - goto rebuild_dpb; - } - case 0x04: - { - struct buffer FAR *bp; - bpb FAR *bpbp; - DWORD rootclst = xdffp->xdff_f.setroot.newrootclst; - if (!ISFAT32(dpb) - || (rootclst != -1 - && (rootclst == 1 - || rootclst > dpb->dpb_xsize))) - { - r->AX = -DE_INVLDPARM; - goto error_out; - } - xdffp->xdff_f.setroot.oldrootclst = dpb->dpb_xrootclst; - if (rootclst != -1) - { - bp = getblock(1, dpb->dpb_unit); - bp->b_flag &= ~(BFR_DATA | BFR_DIR | BFR_FAT); - bp->b_flag |= BFR_VALID | BFR_DIRTY; - bpbp = (bpb FAR *) & bp->b_buffer[BT_BPB]; - bpbp->bpb_xrootclst = rootclst; - } - goto rebuild_dpb; - } - } - - break; - } - /* Extended absolute disk read/write */ - /* TODO(vlp) consider using of the 13-14th bits of SI */ - case 0x05: - { - struct HugeSectorBlock FAR *SectorBlock = - (struct HugeSectorBlock FAR *)MK_FP(r->DS, r->BX); - UBYTE mode; - - if (r->CX != 0xffff || ((r->SI & 1) == 0 && r->SI != 0) - || (r->SI & ~0x6001)) - { - r->AX = -DE_INVLDPARM; - goto error_out; - } - - if (r->DL - 1 >= lastdrive || r->DL == 0) - { - r->AX = 0x207; - goto error_out; - } - CLEAR_CARRY_FLAG(); - - if (r->SI == 0) - mode = DSKREADINT25; - else - mode = DSKWRITEINT26; - - r->AX = - dskxfer(r->DL - 1, SectorBlock->blkno, SectorBlock->buf, - SectorBlock->nblks, mode); - - if (mode == DSKWRITEINT26) - if (r->AX <= 0) - setinvld(r->DL - 1); - - if (r->AX > 0) - { - r->AX = 0x20c; - r->flags |= FLG_CARRY; - return; - } - break; - } - default: - goto error_invalid; - } - break; - } + CLEAR_CARRY_FLAG(); + rc = int21_fat32(&lr); + if (rc != SUCCESS) + goto error_exit; + break; #endif + #ifdef WITHLFNAPI /* FreeDOS LFN helper API functions */ case 0x74: { - switch (r->AL) + switch (lr.AL) { /* Allocate LFN inode */ case 0x01: @@ -1752,34 +1620,54 @@ dispatch: break; /* Free LFN inode */ case 0x02: - rc = lfn_free_inode(r->BX); + rc = lfn_free_inode(lr.BX); break; /* Setup LFN inode */ case 0x03: - rc = lfn_setup_inode(r->BX, ((ULONG)r->CX << 16) | r->DX, ((ULONG)r->SI << 16) | r->DI); + rc = lfn_setup_inode(lr.BX, ((ULONG)lr.CX << 16) | lr.DX, ((ULONG)lr.SI << 16) | lr.DI); break; /* Create LFN entries */ case 0x04: - rc = lfn_create_entries(r->BX, (lfn_inode_ptr)FP_DS_DX); + rc = lfn_create_entries(lr.BX, (lfn_inode_ptr)FP_DS_DX); break; /* Read next LFN */ case 0x05: - rc = lfn_dir_read(r->BX, (lfn_inode_ptr)FP_DS_DX); + rc = lfn_dir_read(lr.BX, (lfn_inode_ptr)FP_DS_DX); break; /* Write SFN pointed by LFN inode */ case 0x06: - rc = lfn_dir_write(r->BX); + rc = lfn_dir_write(lr.BX); break; default: goto error_invalid; } - r->AX = rc; - if (rc < 0) goto error_out; + lr.AX = rc; + if (rc < 0) goto error_exit; else CLEAR_CARRY_FLAG(); break; } #endif } + goto exit_dispatch; + +error_invalid: + rc = DE_INVLDFUNC; +error_exit: + lr.AX = -rc; + CritErrCode = lr.AX; /* Maybe set */ +error_carry: + SET_CARRY_FLAG(); +exit_dispatch: + r->AX = lr.AX; + r->BX = lr.BX; + r->CX = lr.CX; + r->DX = lr.DX; + r->SI = lr.SI; + r->DI = lr.DI; + r->DS = lr.DS; + r->ES = lr.ES; +real_exit: + #ifdef DEBUG if (bDumpRegs) { @@ -1788,6 +1676,7 @@ dispatch: dump(); } #endif + return; } #if 0 @@ -2036,7 +1925,7 @@ VOID ASMCFUNC int2F_12_handler(volatile struct int2f12regs r) case 0x21: /* truename */ - truename(MK_FP(r.ds, r.si), MK_FP(r.es, r.di), 0); + DosTruename(MK_FP(r.ds, r.si), MK_FP(r.es, r.di)); break; diff --git a/kernel/ioctl.c b/kernel/ioctl.c index d22a85a..1a591a5 100644 --- a/kernel/ioctl.c +++ b/kernel/ioctl.c @@ -54,7 +54,7 @@ static BYTE *RcsId = */ -COUNT DosDevIOctl(iregs FAR * r) +COUNT DosDevIOctl(lregs * r) { sft FAR *s; struct dpb FAR *dpbp; @@ -78,10 +78,106 @@ COUNT DosDevIOctl(iregs FAR * r) case 0x07: case 0x0a: case 0x0c: + case 0x10: /* Get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) return DE_INVLDHNDL; + + switch (r->AL) + { + case 0x00: + /* Get the flags from the SFT */ + if (s->sft_flags & SFT_FDEVICE) + r->AX = (s->sft_dev->dh_attr & 0xff00) | s->sft_flags_lo; + else + r->AX = s->sft_flags; + /* Undocumented result, Ax = Dx seen using Pcwatch */ + r->DX = r->AX; + break; + + case 0x01: + /* sft_flags is a file, return an error because you */ + /* can't set the status of a file. */ + if (!(s->sft_flags & SFT_FDEVICE)) + return DE_INVLDFUNC; + + /* Set it to what we got in the DL register from the */ + /* user. */ + r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; + break; + + case 0x02: + nMode = C_IOCTLIN; + goto IoCharCommon; + + case 0x03: + nMode = C_IOCTLOUT; + goto IoCharCommon; + + case 0x06: + if (s->sft_flags & SFT_FDEVICE) + r->AL = s->sft_flags & SFT_FEOF ? 0xFF : 0; + else + r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; + break; + + case 0x07: + if (s->sft_flags & SFT_FDEVICE) + { + nMode = C_OSTAT; + goto IoCharCommon; + } + r->AL = 0; + break; + + case 0x0a: + r->DX = s->sft_flags; + r->AX = 0; + break; + + case 0x0c: + nMode = C_GENIOCTL; + goto IoCharCommon; + + case 0x10: + nMode = C_IOCTLQRY; + IoCharCommon: + if ((s->sft_flags & SFT_FDEVICE) + || ((r->AL == 0x02) && (s->sft_dev->dh_attr & SFT_FIOCTL)) + || ((r->AL == 0x03) && (s->sft_dev->dh_attr & SFT_FIOCTL)) + || ((r->AL == 0x10) && (s->sft_dev->dh_attr & ATTR_QRYIOCTL)) + || ((r->AL == 0x0c) && (s->sft_dev->dh_attr & ATTR_GENIOCTL))) + { + CharReqHdr.r_unit = 0; + CharReqHdr.r_command = nMode; + execrh((request FAR *) & CharReqHdr, s->sft_dev); + + if (CharReqHdr.r_status & S_ERROR) + { + CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; + return DE_DEVICE; + } + + if (r->AL == 0x07) + { + r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; + } + else if (r->AL == 0x02 || r->AL == 0x03) + { + r->AX = CharReqHdr.r_count; + } + + else if (r->AL == 0x0c || r->AL == 0x10) + { + r->AX = CharReqHdr.r_status; + } + break; + } + /* fall through */ + default: + return DE_INVLDFUNC; + } break; case 0x04: @@ -91,7 +187,6 @@ COUNT DosDevIOctl(iregs FAR * r) case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: /* @@ -113,222 +208,125 @@ COUNT DosDevIOctl(iregs FAR * r) /* cdsp = &CDSp[CharReqHdr.r_unit]; */ dpbp = CDSp[CharReqHdr.r_unit].cdsDpb; } - break; + switch (r->AL) + { + case 0x04: + nMode = C_IOCTLIN; + goto IoBlockCommon; + case 0x05: + nMode = C_IOCTLOUT; + goto IoBlockCommon; + case 0x08: + if (!dpbp) + { + return DE_INVLDDRV; + } + if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) + { + nMode = C_REMMEDIA; + goto IoBlockCommon; + } + return DE_INVLDFUNC; + case 0x09: + if (CDSp[CharReqHdr.r_unit].cdsFlags & CDSNETWDRV) + { + r->DX = ATTR_REMOTE; + r->AX = S_DONE | S_BUSY; + } + else + { + if (!dpbp) + { + return DE_INVLDDRV; + } +/* Need to add subst bit 15 */ + r->DX = dpbp->dpb_device->dh_attr; + r->AX = S_DONE | S_BUSY; + } + break; + case 0x0d: + nMode = C_GENIOCTL; + goto IoBlockCommon; + case 0x11: + nMode = C_IOCTLQRY; + IoBlockCommon: + if (!dpbp) + { + return DE_INVLDDRV; + } + if (((r->AL == 0x04) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) + || ((r->AL == 0x05) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) + || ((r->AL == 0x11) + && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) + || ((r->AL == 0x0d) + && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) + { + return DE_INVLDFUNC; + } + + CharReqHdr.r_command = nMode; + execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); + + if (CharReqHdr.r_status & S_ERROR) + { + CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; + return DE_DEVICE; + } + if (r->AL == 0x08) + { + r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; + } + + else if (r->AL == 0x04 || r->AL == 0x05) + { + r->AX = CharReqHdr.r_count; + } + else if (r->AL == 0x0d || r->AL == 0x11) + { + r->AX = CharReqHdr.r_status; + } + break; + + case 0x0e: + nMode = C_GETLDEV; + goto IoLogCommon; + case 0x0f: + nMode = C_SETLDEV; + IoLogCommon: + if (!dpbp) + { + return DE_INVLDDRV; + } + if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) + { + + CharReqHdr.r_command = nMode; + execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); + + if (CharReqHdr.r_status & S_ERROR) + { + CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; + return DE_ACCESS; + } + else + { + r->AL = CharReqHdr.r_unit; + return SUCCESS; + } + } /* fall through */ + default: + return DE_INVLDFUNC; + } + break; + case 0x0b: /* skip, it's a special case. */ - NetDelay = r->CX; if (!r->DX) NetRetry = r->DX; break; - - default: - return DE_INVLDFUNC; - } - - switch (r->AL) - { - case 0x00: - /* Get the flags from the SFT */ - if (s->sft_flags & SFT_FDEVICE) - r->AX = (s->sft_dev->dh_attr & 0xff00) | s->sft_flags_lo; - else - r->AX = s->sft_flags; -/* Undocumented result, Ax = Dx seen using Pcwatch */ - r->DX = r->AX; - break; - - case 0x01: - /* sft_flags is a file, return an error because you */ - /* can't set the status of a file. */ - if (!(s->sft_flags & SFT_FDEVICE)) - return DE_INVLDFUNC; - - /* Set it to what we got in the DL register from the */ - /* user. */ - r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; - break; - - case 0x0c: - nMode = C_GENIOCTL; - goto IoCharCommon; - case 0x02: - nMode = C_IOCTLIN; - goto IoCharCommon; - case 0x10: - nMode = C_IOCTLQRY; - goto IoCharCommon; - case 0x03: - nMode = C_IOCTLOUT; - IoCharCommon: - if ((s->sft_flags & SFT_FDEVICE) - || ((r->AL == 0x02) && (s->sft_dev->dh_attr & SFT_FIOCTL)) - || ((r->AL == 0x03) && (s->sft_dev->dh_attr & SFT_FIOCTL)) - || ((r->AL == 0x10) && (s->sft_dev->dh_attr & ATTR_QRYIOCTL)) - || ((r->AL == 0x0c) && (s->sft_dev->dh_attr & ATTR_GENIOCTL))) - { - CharReqHdr.r_unit = 0; - CharReqHdr.r_command = nMode; - execrh((request FAR *) & CharReqHdr, s->sft_dev); - - if (CharReqHdr.r_status & S_ERROR) - { - CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; - return DE_DEVICE; - } - - if (r->AL == 0x07) - { - r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; - - } - else if (r->AL == 0x02 || r->AL == 0x03) - { - r->AX = CharReqHdr.r_count; - } - - else if (r->AL == 0x0c || r->AL == 0x10) - { - r->AX = CharReqHdr.r_status; - } - break; - } - return DE_INVLDFUNC; - - case 0x0d: - nMode = C_GENIOCTL; - goto IoBlockCommon; - case 0x04: - nMode = C_IOCTLIN; - goto IoBlockCommon; - case 0x11: - nMode = C_IOCTLQRY; - goto IoBlockCommon; - case 0x05: - nMode = C_IOCTLOUT; - IoBlockCommon: - if (!dpbp) - { - return DE_INVLDDRV; - } - if (((r->AL == 0x04) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) - || ((r->AL == 0x05) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) - || ((r->AL == 0x11) - && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) - || ((r->AL == 0x0d) - && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) - { - return DE_INVLDFUNC; - } - - CharReqHdr.r_command = nMode; - execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); - - if (CharReqHdr.r_status & S_ERROR) - { - CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; - return DE_DEVICE; - } - if (r->AL == 0x08) - { - r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; - - } - - else if (r->AL == 0x04 || r->AL == 0x05) - { - r->AX = CharReqHdr.r_count; - - } - else if (r->AL == 0x0d || r->AL == 0x11) - { - r->AX = CharReqHdr.r_status; - } - break; - - case 0x06: - if (s->sft_flags & SFT_FDEVICE) - { - r->AL = s->sft_flags & SFT_FEOF ? 0xFF : 0; - } - else - r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; - break; - - case 0x07: - if (s->sft_flags & SFT_FDEVICE) - { - nMode = C_OSTAT; - goto IoCharCommon; - } - r->AL = 0; - break; - - case 0x08: - if (!dpbp) - { - return DE_INVLDDRV; - } - if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) - { - nMode = C_REMMEDIA; - goto IoBlockCommon; - } - return DE_INVLDFUNC; - - case 0x09: - if (CDSp[CharReqHdr.r_unit].cdsFlags & CDSNETWDRV) - { - r->DX = ATTR_REMOTE; - r->AX = S_DONE | S_BUSY; - } - else - { - if (!dpbp) - { - return DE_INVLDDRV; - } -/* Need to add subst bit 15 */ - r->DX = dpbp->dpb_device->dh_attr; - r->AX = S_DONE | S_BUSY; - } - break; - - case 0x0a: - r->DX = s->sft_flags; - r->AX = 0; - break; - - case 0x0e: - nMode = C_GETLDEV; - goto IoLogCommon; - case 0x0f: - nMode = C_SETLDEV; - IoLogCommon: - if (!dpbp) - { - return DE_INVLDDRV; - } - if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) - { - - CharReqHdr.r_command = nMode; - execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); - - if (CharReqHdr.r_status & S_ERROR) - { - CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; - return DE_ACCESS; - } - else - { - r->AL = CharReqHdr.r_unit; - return SUCCESS; - } - } - return DE_INVLDFUNC; - + default: return DE_INVLDFUNC; } diff --git a/kernel/main.c b/kernel/main.c index 153ff9d..df6602f 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -457,7 +457,6 @@ STATIC void kernel() fmemcpy(p, insertString, 3); Cmd.ctCount += 3; - printf("%d %s\n", Cmd.ctCount, Cmd.ctBuffer); break; } } diff --git a/kernel/newstuff.c b/kernel/newstuff.c index ce6c5d7..de926e2 100644 --- a/kernel/newstuff.c +++ b/kernel/newstuff.c @@ -74,13 +74,13 @@ int DosMkTmp(BYTE FAR * pathname, UWORD attr) { /* create filename from current date and time */ char FAR *ptmp = pathname; - BYTE wd, month, day; - BYTE h, m, s, hund; - WORD sh; - WORD year; + UBYTE wd, month, day; + UBYTE h, m, s, hund; + UWORD sh; + UWORD year; int rc; char name83[13]; - int loop; + int loop = 0; while (*ptmp) ptmp++; @@ -88,52 +88,153 @@ int DosMkTmp(BYTE FAR * pathname, UWORD attr) if (ptmp == pathname || (ptmp[-1] != '\\' && ptmp[-1] != '/')) *ptmp++ = '\\'; - DosGetDate(&wd, &month, &day, (COUNT FAR *) & year); + DosGetDate(&wd, &month, &day, &year); DosGetTime(&h, &m, &s, &hund); sh = s * 100 + hund; - for (loop = 0; loop < 0xfff; loop++) - { + do { sprintf(name83, "%x%x%x%x%x%03x.%03x", year & 0xf, month & 0xf, day & 0xf, h & 0xf, m & 0xf, sh & 0xfff, loop & 0xfff); fmemcpy(ptmp, name83, 13); - if ((rc = DosOpen(pathname, 0)) < 0 && rc != DE_ACCESS /* subdirectory ?? */ - /* todo: sharing collision on - network drive - */ - ) - break; + /* only create new file -- 2001/09/22 ska*/ + rc = (short)DosOpen(pathname, O_LEGACY | O_CREAT | O_RDWR, attr); + } while (rc == DE_FILEEXISTS && loop++ < 0xfff); - if (rc >= 0) - DosClose(rc); - } - - if (rc == DE_FILENOTFND) - { - rc = DosCreat(pathname, attr); - } return rc; } -COUNT get_verify_drive(char FAR * src) +#ifdef DEBUG +#define DEBUG_TRUENAME +#endif + +#define drLetterToNr(dr) ((dr) - 'A') +/* Convert an uppercased drive letter into the drive index */ +#define drNrToLetter(dr) ((dr) + 'A') +/* the other direction */ + + /* In DOS there are no free-standing UNC paths, therefore there + is always a logical drive letter associated with a path + spec. This letter is also the index into the CDS */ + +COUNT get_verify_drive(const char FAR * src) { UBYTE drive; + unsigned flags; /* Do we have a drive? */ if (src[1] == ':') - drive = ((src[0] - 1) | 0x20) - ('a' - 1); - else - return default_drive; - if (drive < lastdrive && CDSp[drive].cdsFlags & CDSVALID) - return drive; + drive = drLetterToNr(DosUpFChar(src[0])); else + drive = default_drive; + + if (drive >= lastdrive) return DE_INVLDDRV; + + /* Entry is disabled or JOINed drives are accessable by the path only */ + flags = CDSp[drive].cdsFlags; + if ((flags & CDSMODEMASK) == 0 || (flags & CDSJOINED) != 0) + return DE_INVLDDRV; + + return drive; } +/* + Definition of functions for the handling of the Current + Directory Structure. + + MUX-11-23: Qualify Remote Filename + DOS-0x60 calls this MUX functions to let the Network Redirector + qualify the filename. According INTRSPY MS DOS 6 does not pre- + process the passed in filename in any way (see attached transcripts). + + The DOS-60 interface TRUENAME looks like this: + + DosTruename(src, dest) { + if (MUX-11-23(src, dest) != Error) + return SUCCESS + return local_truename(src, dest); + } + + The CDS has the following entries: + + char cdsPath[CDSPATHLEN]; + The fully-qualified current working directory of this drive. + The format is DOS :\[{\}] + or UNC \\[{\}]. + The drive indicates the physical drive letter and is the + index into the blk_device[]. + + UWORD cdsFlags; + Indicates what kind this logical drive is: + NETWORK: drive is NOT local \ If both are set, drive is IFS + PHYSICAL: drive is local / If none is set, drive is non-existant + JOIN: drive is joined in as the path cdsPath. This Flag uses the + index into the CDS table to indicate the physical drive. + SUBST: drive substitutes the path cdsPath. + HIDDEN: drive is not included into the redirector's list. + + struct dpb FAR *cdsDpb; + Pointer to the DPB driving the physical drive. In DOS-C, the physical + drive letter is the index into the DPB[]. But for compatibly reason + this field will be set correctly. + + UWORD cdsStartCluster; + For local drives only: This holds the cluster number of + the start of the current working directory of this + logical drive. If 0000h, it's the root directory; if + 0ffffh, the drive was never accessed and has to be read + again. + + void FAR *cdsIFSrecord; + UWORD cdsIFSparameter; + For networked drives only: Holds pointer/parameters to/for IFS + driver. (Well, I don't know.) + + UWORD cdsPathOff; + Number of characters of the cdsPath[], which are hidden. The + logical path is combined by the logical drive letter and the + cdsPath[] part, which is not hidden. + + IFS FAR *cdsIFSdrv; + Will be zeroed for local drives. + + Revision 1.2 1995/12/03 22:17:41 ska + bugfix: Scanning of file name in 8.3 failed on "." and on longer names. + + Revision 1.1 1995/11/09 07:43:30 ska + # + +*/ + +#define PATH_ERROR goto errRet +#define PATHLEN 128 + + +/* Map a logical path into a physical one. + + 1) Uppercasing path. + 2) Flipping '/' -> '\\'. + 3) Removing empty directory components & ".". + 4) Processing ".." components. + 5) Convert path components into 8.3 convention. + 6) Make it fully-qualified. + 7) Map it to SUBST/UNC. + 8) Map to JOIN. + + Return: + *cdsItem will be point to the appropriate CDS entry. This will allow + the caller to aquire the DPB or the IFS informtion of this entry. + error number + Return value: + DE_FILENOTFND, or DE_PATHNOTFND (as described in RBIL) + If the output path pnfo->physPath exceeds the length MAX_PATH, the error + DE_FILENOTFND will be returned. +*/ + /* * Added support for external and internal calls. * Clean buffer before use. Make the true path and expand file names. @@ -157,27 +258,127 @@ COUNT get_verify_drive(char FAR * src) */ -COUNT truename(char FAR * src, char FAR * dest, COUNT t) +#ifdef DEBUG_TRUENAME +#define tn_printf(x) printf x +#else +#define tn_printf(x) +#endif + +#define PNE_WILDCARD 1 +#define PNE_DOT 2 + +#define addChar(c) \ +{ \ + if (p - dest >= SFTMAX) PATH_ERROR; /* path too long */ \ + *p++ = c; \ +} + +/* helper for truename: parses either name or extension */ +STATIC int parse_name_ext(int i, const char FAR **src, char **cp, char *dest) { - static char buf[128] = "A:\\\0\0\0\0\0\0\0\0\0"; - char *bufp = buf + 3; - COUNT i, rootEndPos = 2; /* renamed x to rootEndPos - Ron Cemer */ + int retval = SUCCESS; + char *p = *cp; + char c; + + while(1) switch(c=*(*src)++) + { + case '.': + retval |= PNE_DOT; + /* fall through */ + case '/': + case '\\': + case '\0': + *cp = p; + return retval; + case '*': + retval |= PNE_WILDCARD; + /* register the wildcard, even if no '?' is appended */ + if (i) do + { + addChar('?'); + } while(--i); + /** Alternative implementation: + if (i) + { + if (dest + SFTMAX - *p < i) + PATH_ERROR; + fmemset(p, '?', i); + p += i; + } **/ + break; + case '?': + retval |= PNE_WILDCARD; + /* fall through */ + default: + if (i) { /* name length in limits */ + --i; + addChar(c); + } + } + + errRet: + return -1; +} + +COUNT truename(const char FAR * src, char * dest, COUNT mode) +{ + COUNT i; struct dhdr FAR *dhp; - BYTE FAR *froot; - WORD d; + const char FAR *froot; + COUNT result; + int gotAnyWildcards = 0; + struct cds FAR *cdsEntry; + char *p = dest; /* dynamic pointer into dest */ + char *rootPos; + enum { DONT_ADD, ADD, ADD_UNLESS_LAST } addSep; - dest[0] = '\0'; - - i = get_verify_drive(src); - if (i < 0) - return DE_INVLDDRV; - - buf[0] = i + 'A'; - buf[1] = ':'; /* Just to be sure */ + tn_printf(("truename(%S)\n", src)); /* First, adjust the source pointer */ src = adjust_far(src); + /* In opposite of the TRUENAME shell command, an empty string is + rejected by MS DOS 6 */ + if (src[0] == '\0') + return DE_FILENOTFND; + + result = get_verify_drive(src); + if (result < SUCCESS) + return result; + + cdsEntry = &CDSp[result]; + tn_printf(("CDS entry: #%u @%p (%u) '%S'\n", result, cdsEntry, + cdsEntry->cdsBackslashOffset, cdsEntry->cdsCurrentPath)); + /* is the current_ldt thing necessary for compatibly?? + -- 2001/09/03 ska*/ + current_ldt = cdsEntry; + if (cdsEntry->cdsFlags & CDSNETWDRV) + result |= IS_NETWORK; + + dhp = IsDevice(src); + if (dhp) + result |= IS_DEVICE; + + /* Try if the Network redirector wants to do it */ + dest[0] = '\0'; /* better probable for sanity check below -- + included by original truename() */ + /* MUX succeeded and really something */ + if (QRemote_Fn(dest, src) && dest[0] != '\0') + { + tn_printf(("QRemoteFn() returned: \"%S\"\n", dest)); +#ifdef DEBUG_TRUENAME + if (strlen(dest) >= SFTMAX) + panic("Truename: QRemote_Fn() overflowed output buffer"); +#endif + if (dest[2] == '/' && (result & IS_DEVICE)) + result &= ~IS_NETWORK; + return result; + } + + /* Redirector interface failed --> proceed with local mapper */ + dest[0] = drNrToLetter(result & 0x1f); + dest[1] = ':'; + /* Do we have a drive? */ if (src[1] == ':') src += 2; @@ -188,344 +389,320 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t) */ /* check for a device */ - if ((*src != '.') && (*src != '\\') && (*src != '/') - && ((dhp = IsDevice(src)) != NULL)) + dest[2] = '\\'; + if (result & IS_DEVICE) { - froot = get_root(src); - - /* /// Bugfix: NUL.LST is the same as NUL. This is true for all - devices. On a device name, the extension is irrelevant - as long as the name matches. - - Ron Cemer */ - - buf[2] = '/'; - /* /// Bug: should be only copying up to first space. - - Ron Cemer */ - - for (d = 0; - d < FNAME_SIZE && dhp->dh_name[d] != 0 && dhp->dh_name[d] != ' '; - d++) - *bufp++ = dhp->dh_name[d]; - /* /// DOS will return C:/NUL.LST if you pass NUL.LST in. - DOS will also return C:/NUL.??? if you pass NUL.* in. - Code added here to support this. - - Ron Cemer */ - while ((*froot != '.') && (*froot != '\0')) - froot++; - if (*froot) - froot++; - if (*froot) + if (froot == src || froot == src + 5) { - *bufp++ = '.'; - for (i = 0; i < FEXT_SIZE; i++) + if (froot == src + 5) { - if ((*froot == '\0') || (*froot == '.')) - break; - if (*froot == '*') - { - for (; i < FEXT_SIZE; i++) - *bufp++ = '?'; - break; - } - *bufp++ = *froot++; + fmemcpy(dest + 3, src, 5); + DosUpMem(dest + 3, 5); + if (dest[3] == '/') dest[3] = '\\'; + if (dest[7] == '/') dest[7] = '\\'; + } + if (froot == src || memcmp(dest + 3, "\\DEV\\", 5) == 0) + { + /* /// Bugfix: NUL.LST is the same as NUL. This is true for all + devices. On a device name, the extension is irrelevant + as long as the name matches. + - Ron Cemer */ + dest[2] = '/'; + result &= ~IS_NETWORK; + /* /// DOS will return C:/NUL.LST if you pass NUL.LST in. + DOS will also return C:/NUL.??? if you pass NUL.* in. + Code added here to support this. + - Ron Cemer */ + src = froot; } } - /* /// End of code additions. - Ron Cemer */ - goto exit_tn; } - - /* /// Added to adjust for filenames which begin with ".\" - * The problem was manifesting itself in the inability - * to run an program whose filename (without the extension) - * was longer than six characters and the PATH variable - * contained ".", unless you explicitly specified the full - * path to the executable file. - * Jun 11, 2000 - rbc */ - /* /// Changed to "while" from "if". - Ron Cemer */ - while ((src[0] == '.') && (src[1] == '\\')) - src += 2; - - current_ldt = &CDSp[i]; - - /* Always give the redirector a chance to rewrite the filename */ - fmemcpy(bufp - 1, src, sizeof(buf) - (bufp - buf)); - if ((t == FALSE) && (QRemote_Fn(buf, dest) == SUCCESS) - && (dest[0] != '\0')) + + /* Make fully-qualified logical path */ + /* register these two used characters and the \0 terminator byte */ + /* we always append the current dir to stat the drive; + the only exceptions are devices without paths */ + rootPos = p = dest + 2; + if (*p != '/') /* i.e., it's a backslash! */ { - return SUCCESS; - } - else - { - bufp[-1] = '\\'; - } - if (t == FALSE) - { - fmemcpy(buf, current_ldt->cdsCurrentPath, current_ldt->cdsJoinOffset); - bufp = buf + current_ldt->cdsJoinOffset; - rootEndPos = current_ldt->cdsJoinOffset; /* renamed x to rootEndPos - Ron Cemer */ - *bufp++ = '\\'; - } - - if (*src != '\\' && *src != '/') /* append current dir */ - { - DosGetCuDir((UBYTE) (i + 1), bufp); - if (*bufp) + if (!(mode & CDS_MODE_SKIP_PHYSICAL)) { - while (*bufp) - bufp++; - *bufp++ = '\\'; - } - } - else - src++; + tn_printf(("SUBSTing from: %S\n", cdsEntry->cdsCurrentPath)); +/* What to do now: the logical drive letter will be replaced by the hidden + portion of the associated path. This is necessary for NETWORK and + SUBST drives. For local drives it should not harm. + This is actually the reverse mechanism of JOINED drives. */ -/*move_name:*/ - - /* /// The block inside the "#if (0) ... #endif" is - seriously broken. New code added below to replace it. - This eliminates many serious bugs, specifically - with FreeCOM where truename is required to work - according to the DOS specification in order for - the COPY and other file-related commands to work - properly. - This should be a major improvement to all apps which - use truename. - - Ron Cemer */ - -#if (0) -/* - * The code here is brain dead. It works long as the calling - * function are operating with in normal parms. - * jt - */ - n = 9; - /* convert all forward slashes to backslashes, and uppercase all characters */ - while (*src) - { - char c; - c = *src++; - if (!n) - return DE_PATHNOTFND; /* do this for now */ - n--; - switch (c) - { - case '*': - if (*src == '.') - { - while (n--) - *bufp++ = '?'; - break; - } - else - { - if (src[-2] == '.') - { - while (n--) - *bufp++ = '?'; - break; - } - else - { - while (n--) - *bufp++ = '?'; - break; - } - } - case '/': /* convert to backslash */ - case '\\': - - if (bufp[-1] != '\\') - { - *bufp++ = '\\'; - n = 9; - } - break; - - /* look for '.' and '..' dir entries */ - case '.': - if (bufp[-1] == '\\') - { - if (*src == '.' && (src[1] == '/' || src[1] == '\\' || !src[1])) - { - /* '..' dir entry: rewind bufp to last backslash */ - - for (bufp -= 2; *bufp != '\\'; bufp--) - { - if (bufp < buf + rootEndPos) /* '..' illegal in root dir */ - return DE_PATHNOTFND; - } - src++; - if (bufp[-1] == ':') - bufp++; - } - else if (*src == '/' || *src == '\\' || *src == 0) - break; - /* --bufp; */ - else - return DE_PATHNOTFND; - } - else if (*src == '/' || *src == '\\' || *src == 0) - { - break; - } - else - { - n = 4; - *bufp++ = c; - } - break; - - default: - *bufp++ = c; - break; - } - } - - /* remove trailing backslashes */ - while (bufp[-1] == '\\') - --bufp; -#endif - -/* /// Beginning of new code. - Ron Cemer */ - bufp--; - { - char c, *bufend = buf + (sizeof(buf) - 1); - int gotAnyWildcards = 0; - int seglen, copylen, state; - int error = DE_PATHNOTFND; - while ((*src) && (bufp < bufend)) - { - /* Skip duplicated slashes. */ - while ((*src == '/') || (*src == '\\')) - src++; - if (!(*src)) - break; - /* Find the end of this segment in the source string. */ - for (seglen = 0;; seglen++) + fmemcpy(dest, cdsEntry->cdsCurrentPath, cdsEntry->cdsBackslashOffset); + if (cdsEntry->cdsFlags & CDSSUBST) { - c = src[seglen]; - if (c == '\0') - { - error = DE_FILENOTFND; - break; + /* The drive had been changed --> update the CDS pointer */ + if (dest[1] == ':') + { /* sanity check if this really is a local drive still */ + unsigned i = drLetterToNr(dest[0]); + + if (i < lastdrive) /* sanity check #2 */ + result = (result & 0xffe0) | i; } - else if ((c == '/') || (c == '\\')) - break; } - if (seglen > 0) - { - /* Ignore all ".\" or "\." path segments. */ - if ((seglen != 1) || (*src != '.')) - { - /* Apply ".." to the path by removing - last path segment from buf. */ - if ((seglen == 2) && (src[0] == '.') && (src[1] == '.')) - { - if (bufp > (buf + rootEndPos)) - { - bufp--; - while ((bufp > (buf + rootEndPos)) - && (*bufp != '/') && (*bufp != '\\')) - bufp--; - } - else - { - /* .. in root dir illegal */ - return error; - } - } - else - { - /* New segment. If any wildcards in previous - segment(s), this is an invalid path. */ - if (gotAnyWildcards || src[0] == '.') - return error; - /* Append current path segment to result. */ - *(bufp++) = '\\'; - if (bufp >= bufend) - break; - copylen = state = 0; - for (i = 0; ((i < seglen) && (bufp < bufend)); i++) - { - c = src[i]; - gotAnyWildcards |= ((c == '?') || (c == '*')); - switch (state) - { - case 0: /* Copying filename (excl. extension) */ - if (c == '*') - { - while (copylen < FNAME_SIZE) - { - *(bufp++) = '?'; - if (bufp >= bufend) - break; - copylen++; - } - break; - } - if (c == '.') - { - if (src[i + 1] != '.' && i + 1 < seglen) - *(bufp++) = '.'; - copylen = 0; - state = 1; /* Copy extension next */ - break; - } - if (copylen < FNAME_SIZE) - { - *(bufp++) = c; - copylen++; - break; - } - break; - case 1: /* Copying extension */ - if (c == '*') - { - while (copylen < FEXT_SIZE) - { - *(bufp++) = '?'; - if (bufp >= bufend) - break; - copylen++; - } - } - if (c == '.') - return error; - if (copylen < FEXT_SIZE) - { - *(bufp++) = c; - copylen++; - } - break; - } - } - } - } - } /* if (seglen > 0) */ - src += seglen; - if (*src) - src++; - } /* while ( (*src) && (bufp < bufend) ) */ + rootPos = p = dest + current_ldt->cdsBackslashOffset; + *p = '\\'; /* force backslash! */ + } + p++; + DosGetCuDir((result & 0x1f) + 1, p); + if (*src != '\\' && *src != '/') + p += strlen(p); + else /* skip the absolute path marker */ + src++; + /* remove trailing separator */ + if (p[-1] == '\\') p--; } -/* /// End of new code. - Ron Cemer */ - if (bufp == buf + 2) - ++bufp; + /* append the path specified in src */ + addSep = ADD; /* add separator */ -exit_tn: + while(*src) + { + /* New segment. If any wildcards in previous + segment(s), this is an invalid path. */ + if (gotAnyWildcards) + return DE_PATHNOTFND; + switch(*src++) + { + case '/': + case '\\': /* skip multiple separators (duplicated slashes) */ + addSep = ADD; + break; + case '.': /* special directory component */ + switch(*src) + { + case '/': + case '\\': + case '\0': + /* current path -> ignore */ + addSep = ADD_UNLESS_LAST; + /* If (/ or \) && no ++src + --> addSep = ADD next turn */ + continue; /* next char */ + case '.': /* maybe ".." entry */ + switch(src[1]) + { + case '/': + case '\\': + case '\0': + /* remove last path component */ + while(*--p != '\\') + if (p <= rootPos) /* already on root */ + return DE_PATHNOTFND; + /* the separator was removed -> add it again */ + ++src; /* skip the second dot */ + /* If / or \, next turn will find them and + assign addSep = ADD */ + addSep = ADD_UNLESS_LAST; + continue; /* next char */ + } + } + + /* ill-formed .* or ..* entries => return error */ + errRet: + /* The error is either PATHNOTFND or FILENOTFND + depending on if it is not the last component */ + return fstrchr(src, '/') == 0 && fstrchr(src, '\\') == 0 + ? DE_FILENOTFND + : DE_PATHNOTFND; + default: /* normal component */ + if (addSep != DONT_ADD) + { /* append backslash */ + addChar(*rootPos); + addSep = DONT_ADD; + } + + /* append component in 8.3 convention */ + --src; + /* first character skipped in switch() */ + i = parse_name_ext(FNAME_SIZE, &src, &p, dest); + if (i == -1) + PATH_ERROR; + if (i & PNE_WILDCARD) + gotAnyWildcards = TRUE; + /* strip trailing dot */ + if ((i & PNE_DOT) && *src != '/' && *src != '\\' && *src != '\0') + { + /* we arrive here only when an extension-dot has been found */ + addChar('.'); + i = parse_name_ext(FEXT_SIZE, &src, &p, dest); + if (i == -1 || i & PNE_DOT) /* multiple dots are ill-formed */ + PATH_ERROR; + if (i & PNE_WILDCARD) + gotAnyWildcards = TRUE; + } + --src; /* terminator or separator was skipped */ + break; + } + } + if (addSep == ADD) + { + /* MS DOS preserves a trailing '\\', so an access to "C:\\DOS\\" + or "CDS.C\\" fails. */ + /* But don't add the separator, if the last component was ".." */ + addChar('\\'); + } + + *p = '\0'; /* add the string terminator */ + DosUpFString(rootPos); /* upcase the file/path name */ + +/** Note: + Only the portions passed in by the user are upcased, because it is + assumed that the CDS is configured correctly and if it contains + lower case letters, it is required so **/ + + tn_printf(("Absolute logical path: \"%s\"\n", dest)); + + /* Now, all the steps 1) .. 7) are fullfilled. Join now */ + /* search, if this path is a joined drive */ - *bufp++ = 0; - - /* finally, uppercase everything */ - DosUpString(buf); - - /* copy to user's buffer */ - fmemcpy(dest, buf, bufp - buf); - - return SUCCESS; + if (dest[2] != '/' && (!(mode & CDS_MODE_SKIP_PHYSICAL)) && njoined) + { + for(i = 0; i < lastdrive; ++i) + { + /* How many bytes must match */ + size_t j = fstrlen(CDSp[i].cdsCurrentPath); + /* the last component must end before the backslash offset and */ + /* the path the drive is joined to leads the logical path */ + if ((CDSp[i].cdsFlags & CDSJOINED) && (dest[j] == '\\' || dest[j] == '\0') + && fmemcmp(dest, CDSp[i].cdsCurrentPath, j) == 0) + { /* JOINed drive found */ + dest[0] = drNrToLetter(i); /* index is physical here */ + dest[1] = ':'; + if (dest[j] == '\0') + { /* Reduce to root direc */ + dest[2] = '\\'; + dest[3] = 0; + /* move the relative path right behind the drive letter */ + } + else if (j != 2) + { + strcpy(dest + 2, dest + j); + } + result = (result & 0xffe0) | i; + current_ldt = &CDSp[i]; + result &= ~IS_NETWORK; + if (current_ldt->cdsFlags & CDSNETWDRV) + result |= IS_NETWORK; + tn_printf(("JOINed path: \"%S\"\n", dest)); + return result; + } + } + /* nothing found => continue normally */ + } + if ((mode & CDS_MODE_CHECK_DEV_PATH) && (result & IS_DEVICE) && + !(result & IS_NETWORK) && dest[2] != '/' && !dir_exists(dest)) + return DE_PATHNOTFND; + + tn_printf(("Physical path: \"%s\"\n", dest)); + return result; } +#if 0 +/********************************************** + Result of INTRSPY + + Calling RBIL's INT.COM in MS DOS v6.22 + +=== Script: MUX.SCR + +intercept 2fh + function 11h ; network redirector + subfunction 23h ; Qualify path and filename + on_entry + output "1123: IN: " (ds:SI->byte,asciiz,64) + on_exit + if (cflag == 1) + sameline " [FAIL " ax "]" + output "1123: OUT: " (es:dI->byte,asciiz,64) + output "1123: orig buffer: " (ds:sI->byte,asciiz,64) + function 12h + subfunction 21h + on_entry + output "1221: IN: " (ds:SI->byte,asciiz,64) + on_exit + if (cflag == 1) + sameline " [FAIL " ax "]" + output "1221: OUT: " (es:dI->byte,asciiz,64) + +=== Batch file: SPY_INT.BAT +@echo off +if exist report.out del report.out +cmdspy stop +cmdspy flush +cmdspy restart +int ax=0x6000 -buf ds:si="abcöflkgsxkf\0" -buf es:di="%256s" -int 0x21 -d es:di:128 >spy_int.out +cmdspy stop +cmdspy report report.out +more report.out +=== Intspy report file: REPORT.OUT +1123: IN: C:\INTRSPY\SPY_INT.BAT [FAIL 0001] +1123: OUT:  +1123: orig buffer: C:\INTRSPY\SPY_INT.BAT +1123: IN: int.??? [FAIL 0001] +1123: OUT: C:\INTRSPY +1123: orig buffer: int.??? +1123: IN: C:\TOOL\int.??? [FAIL 0001] +1123: OUT: C:\INTRSPY +1123: orig buffer: C:\TOOL\int.??? +1123: IN: spy_int.out [FAIL 0001] +1123: OUT: C:\TOOL\INT.??? +1123: orig buffer: spy_int.out +1123: IN: C:\TOOL\INT.COM [FAIL 0001] +1123: OUT: C:\INTRSPY\SPY_INT.OUT +1123: orig buffer: C:\TOOL\INT.COM +1123: IN: abcöflkgsxkf [FAIL 0001] +1123: OUT: C:\TOOL\INT.COM +1123: orig buffer: abcöflkgsxkf +1123: IN: C:\INTRSPY\SPY_INT.BAT [FAIL 0001] +1123: OUT: C:\INTRSPY\ABCÖFLKG +1123: orig buffer: C:\INTRSPY\SPY_INT.BAT +1123: IN: cmdspy.??? [FAIL 0001] +1123: OUT: C:\INTRSPY +1123: orig buffer: cmdspy.??? +1123: IN: C:\INTRSPY\CMDSPY.EXE [FAIL 0001] +1123: OUT: C:\INTRSPY +1123: orig buffer: C:\INTRSPY\CMDSPY.EXE +=== INT.COM output: SPY_INT.OUT + 000 CX=0000 DX=0000 +SI=4A5E DI=4A76 BP=FF70 SP=FF64 +CS=0000 DS=279D ES=279D SS=0000 CPU Flags: 0n00oditsz0a0p1c + +INT: 0x21 + +AX=0059 BX=0000 CX=0000 DX=0000 +SI=4A5E DI=4A76 BP=FF70 SP=FF64 +CS=0000 DS=279D ES=279D SS=0000 CPU Flags: 0N11odItSz0A0P1c +DOSERR: 0000 (0) + +* { +43(C) 3A(:) 5C(\) 49(I) 4E(N) 54(T) 52(R) 53(S) 50(P) 59(Y) 5C(\) 41(A) +42(B) 43(C) 99(Ö) 46(F) 4C(L) 4B(K) 47(G) 00(.) 3D(=) 30(0) 30(0) 30(0) +30(0) 20( ) 20( ) 20( ) 43(C) 58(X) 3D(=) 30(0) 30(0) 30(0) 30(0) 28(() +30(0) 29()) 20( ) 32(2) 38(8) 28(() 28(() 29()) 20( ) 33(3) 30(0) 28(() +30(0) 29()) 20( ) 32(2) 39(9) 28(() 29()) 29()) 20( ) 32(2) 30(0) 28(() +20( ) 29()) 20( ) 33(3) 32(2) 28(() 32(2) 29()) 20( ) 33(3) 38(8) 28(() +38(8) 29()) 20( ) 32(2) 38(8) 28(() 28(() 29()) 20( ) 32(2) 38(8) 28(() +28(() 29()) 20( ) 32(2) 39(9) 28(() 29()) 29()) 20( ) 32(2) 30(0) 28(() +20( ) 29()) 20( ) 33(3) 33(3) 28(() 33(3) 29()) 20( ) 33(3) 30(0) 28(() +30(0) 29()) 20( ) 32(2) 38(8) 28(() 28(() 29()) 20( ) 33(3) 30(0) 28(() +30(0) 29()) 20( ) 32(2) 39(9) 28(() 29()) 29()) } +=== + +The actual interesting lines are the 6th "IN:" of the report file. +The DOS interface passed _exactly_ the same string to MUX-11-23 as +written on command line, the same applied to "con\0", a device driver. + +***************************************/ + +#endif + /* * Log: newstuff.c,v - for newer entries see "cvs log newstuff.c" * diff --git a/kernel/nls.c b/kernel/nls.c index 28de454..80ec641 100644 --- a/kernel/nls.c +++ b/kernel/nls.c @@ -586,7 +586,7 @@ COUNT DosSetCountry(UWORD cntry) /* * Called for DOS-66-01 get CP */ -COUNT DosGetCodepage(UWORD FAR * actCP, UWORD FAR * sysCP) +COUNT DosGetCodepage(UWORD * actCP, UWORD * sysCP) { *sysCP = nlsInfo.sysCodePage; *actCP = nlsInfo.actPkg->cp; diff --git a/kernel/proto.h b/kernel/proto.h index 5330aba..512f59b 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -50,6 +50,7 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, /* *** End of change */ /* chario.c */ +UCOUNT BinaryCharIO(struct dhdr FAR * dev, UCOUNT n, void FAR * bp, unsigned command, COUNT *err); VOID sto(COUNT c); VOID cso(COUNT c); VOID mod_cso(REG UCOUNT c); @@ -66,36 +67,33 @@ UCOUNT sti(keyboard * kp); sft FAR *get_sft(UCOUNT); /* dosfns.c */ -BYTE FAR *get_root(BYTE FAR *); +const char FAR *get_root(const char FAR *); BOOL check_break(void); -UCOUNT GenericReadSft(sft far * sftp, UCOUNT n, BYTE FAR * bp, - COUNT FAR * err, BOOL force_binary); +UCOUNT GenericReadSft(sft far * sftp, UCOUNT n, void FAR * bp, + COUNT * err, BOOL force_binary); COUNT SftSeek(sft FAR * sftp, LONG new_pos, COUNT mode); /*COUNT DosRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err); */ -#define GenericRead(hndl, n, bp, err, t) GenericReadSft(get_sft(hndl), n, bp, err, t) -#define DosRead(hndl, n, bp, err) GenericRead(hndl, n, bp, err, FALSE) -#define DosReadSft(sftp, n, bp, err) GenericReadSft(sftp, n, bp, err, FALSE) -UCOUNT DosWriteSft(sft FAR * sftp, UCOUNT n, const BYTE FAR * bp, - COUNT FAR * err); -#define DosWrite(hndl, n, bp, err) DosWriteSft(get_sft(hndl), n, bp, err) -COUNT DosSeek(COUNT hndl, LONG new_pos, COUNT mode, ULONG * set_pos); -COUNT DosCreat(BYTE FAR * fname, COUNT attrib); -COUNT DosCreatSft(BYTE * fname, COUNT attrib); -COUNT CloneHandle(COUNT hndl); -COUNT DosDup(COUNT Handle); -COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle); -COUNT DosOpen(BYTE FAR * fname, COUNT mode); -COUNT DosOpenSft(BYTE * fname, COUNT mode); +UCOUNT BinaryReadSft(sft FAR * s, void *bp, COUNT *err); +#define BinaryRead(hndl, bp, err) BinaryReadSft(get_sft(hndl), bp, err) +UCOUNT DosRWSft(sft FAR * s, UCOUNT n, void FAR * bp, COUNT *err, int mode); +#define DosRead(hndl, n, bp, err) DosRWSft(get_sft(hndl), n, bp, err, XFR_READ) +#define DosWrite(hndl, n, bp, err) DosRWSft(get_sft(hndl), n, bp, err, XFR_WRITE) +ULONG DosSeek(COUNT hndl, LONG new_pos, COUNT mode); +long DosOpen(char FAR * fname, unsigned flags, unsigned attrib); +COUNT CloneHandle(unsigned hndl); +long DosDup(unsigned Handle); +COUNT DosForceDup(unsigned OldHandle, unsigned NewHandle); +long DosOpenSft(char FAR * fname, unsigned flags, unsigned attrib); COUNT DosClose(COUNT hndl); COUNT DosCloseSft(WORD sft_idx, BOOL commitonly); #define DosCommit(hndl) DosCloseSft(get_sft_idx(hndl), TRUE) -BOOL DosGetFree(UBYTE drive, UCOUNT FAR * spc, UCOUNT FAR * navc, - UCOUNT FAR * bps, UCOUNT FAR * nc); +BOOL DosGetFree(UBYTE drive, UWORD * spc, UWORD * navc, + UWORD * bps, UWORD * nc); COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s); COUNT DosChangeDir(BYTE FAR * s); COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name); COUNT DosFindNext(void); -COUNT DosGetFtime(COUNT hndl, date FAR * dp, time FAR * tp); +COUNT DosGetFtime(COUNT hndl, date * dp, time * tp); COUNT DosSetFtimeSft(WORD sft_idx, date dp, time tp); #define DosSetFtime(hndl, dp, tp) DosSetFtimeSft(get_sft_idx(hndl), (dp), (tp)) COUNT DosGetFattr(BYTE FAR * name); @@ -104,21 +102,20 @@ UBYTE DosSelectDrv(UBYTE drv); COUNT DosDelete(BYTE FAR * path, int attrib); COUNT DosRename(BYTE FAR * path1, BYTE FAR * path2); COUNT DosRenameTrue(BYTE * path1, BYTE * path2, int attrib); -COUNT DosMkdir(BYTE FAR * dir); -COUNT DosRmdir(BYTE FAR * dir); -struct dhdr FAR *IsDevice(BYTE FAR * FileName); +COUNT DosMkdir(const char FAR * dir); +COUNT DosRmdir(const char FAR * dir); +struct dhdr FAR *IsDevice(const char FAR * FileName); BOOL IsShareInstalled(void); COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock); sft FAR *idx_to_sft(COUNT SftIndex); COUNT get_sft_idx(UCOUNT hndl); +COUNT DosTruename(const char FAR * src, char FAR * dest); /*dosidle.asm */ VOID ASMCFUNC DosIdle_int(void); /* dosnames.c */ -VOID SpacePad(BYTE *, COUNT); -COUNT ParseDosName(BYTE *, COUNT *, BYTE *, BYTE *, BYTE *, BOOL); -/*COUNT ParseDosPath(BYTE *, COUNT *, BYTE *, BYTE FAR *); */ +int ParseDosName(const char *, char *, BOOL); /* error.c */ VOID dump(void); @@ -127,7 +124,7 @@ VOID fatal(BYTE * err_msg); /* fatdir.c */ VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart); -f_node_ptr dir_open(BYTE * dirname); +f_node_ptr dir_open(const char *dirname); COUNT dir_read(REG f_node_ptr fnp); BOOL dir_write(REG f_node_ptr fnp); VOID dir_close(REG f_node_ptr fnp); @@ -138,13 +135,12 @@ int FileName83Length(BYTE * filename83); /* fatfs.c */ ULONG clus2phys(CLUSTER cl_no, struct dpb FAR * dpbp); -COUNT dos_open(BYTE * path, COUNT flag); -BOOL fcmp(BYTE * s1, BYTE * s2, COUNT n); -BOOL fcmp_wild(BYTE FAR * s1, BYTE FAR * s2, COUNT n); +long dos_open(char * path, unsigned flag, unsigned attrib); +BOOL fcbmatch(const char *fcbname1, const char *fcbname2); +BOOL fcmp_wild(const char * s1, const char * s2, unsigned n); VOID touc(BYTE * s, COUNT n); COUNT dos_close(COUNT fd); COUNT dos_commit(COUNT fd); -COUNT dos_creat(BYTE * path, int attrib); COUNT dos_delete(BYTE * path, int attrib); COUNT dos_rmdir(BYTE * path); COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib); @@ -152,8 +148,7 @@ date dos_getdate(void); time dos_gettime(void); COUNT dos_getftime(COUNT fd, date FAR * dp, time FAR * tp); COUNT dos_setftime(COUNT fd, date dp, time tp); -LONG dos_getcufsize(COUNT fd); -LONG dos_getfsize(COUNT fd); +ULONG dos_getfsize(COUNT fd); BOOL dos_setfsize(COUNT fd, LONG size); COUNT dos_mkdir(BYTE * dir); BOOL last_link(f_node_ptr fnp); @@ -163,6 +158,7 @@ COUNT dos_read(COUNT fd, VOID FAR * buffer, UCOUNT count); COUNT dos_write(COUNT fd, const VOID FAR * buffer, UCOUNT count); LONG dos_lseek(COUNT fd, LONG foffset, COUNT origin); CLUSTER dos_free(struct dpb FAR * dpbp); +BOOL dir_exists(char * path); VOID trim_path(BYTE FAR * s); @@ -171,6 +167,7 @@ COUNT dos_cd(struct cds FAR * cdsp, BYTE * PathName); f_node_ptr get_f_node(void); VOID release_f_node(f_node_ptr fnp); VOID dos_setdta(BYTE FAR * newdta); +COUNT dos_getfattr_fd(COUNT fd); COUNT dos_getfattr(BYTE * name); COUNT dos_setfattr(BYTE * name, UWORD attrp); COUNT media_check(REG struct dpb FAR * dpbp); @@ -192,43 +189,35 @@ int DosCharInput(VOID); VOID DosDirectConsoleIO(iregs FAR * r); VOID DosCharOutput(COUNT c); VOID DosDisplayOutput(COUNT c); -VOID FatGetDrvData(UCOUNT drive, UCOUNT FAR * spc, UCOUNT FAR * bps, - UCOUNT FAR * nc, BYTE FAR ** mdp); -WORD FcbParseFname(int wTestMode, const BYTE FAR ** lpFileName, fcb FAR * lpFcb); +BYTE FAR *FatGetDrvData(UBYTE drive, UWORD * spc, UWORD * bps, + UWORD * nc); +UWORD FcbParseFname(int *wTestMode, const BYTE FAR *lpFileName, fcb FAR * lpFcb); const BYTE FAR *ParseSkipWh(const BYTE FAR * lpFileName); BOOL TestCmnSeps(BYTE FAR * lpFileName); BOOL TestFieldSeps(BYTE FAR * lpFileName); const BYTE FAR *GetNameField(const BYTE FAR * lpFileName, BYTE FAR * lpDestField, COUNT nFieldSize, BOOL * pbWildCard); -typedef BOOL FcbFunc_t (xfcb FAR *, COUNT *, UCOUNT); -FcbFunc_t FcbRead, FcbWrite; -BOOL FcbGetFileSize(xfcb FAR * lpXfcb); -BOOL FcbSetRandom(xfcb FAR * lpXfcb); -BOOL FcbCalcRec(xfcb FAR * lpXfcb); -BOOL FcbRandomBlockRead(xfcb FAR * lpXfcb, COUNT nRecords, - COUNT * nErrorCode); -BOOL FcbRandomBlockWrite(xfcb FAR * lpXfcb, COUNT nRecords, - COUNT * nErrorCode); -BOOL FcbRandomIO(xfcb FAR * lpXfcb, COUNT * nErrorCode, FcbFunc_t *FcbFunc); -BOOL FcbOpenCreate(xfcb FAR * lpXfcb, BOOL Create); -#define FcbOpen(fcb) FcbOpenCreate(fcb, FALSE) -#define FcbCreate(fcb) FcbOpenCreate(fcb, TRUE) -void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive); -BOOL FcbDelete(xfcb FAR * lpXfcb); -BOOL FcbRename(xfcb FAR * lpXfcb); -BOOL FcbClose(xfcb FAR * lpXfcb); -VOID FcbCloseAll(VOID); -BOOL FcbFindFirst(xfcb FAR * lpXfcb); -BOOL FcbFindNext(xfcb FAR * lpXfcb); +UBYTE FcbReadWrite(xfcb FAR *, UCOUNT, int); +UBYTE FcbGetFileSize(xfcb FAR * lpXfcb); +void FcbSetRandom(xfcb FAR * lpXfcb); +UBYTE FcbRandomBlockIO(xfcb FAR * lpXfcb, COUNT nRecords, int mode); +UBYTE FcbRandomIO(xfcb FAR * lpXfcb, int mode); +UBYTE FcbOpen(xfcb FAR * lpXfcb, unsigned flags); +int FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive); +UBYTE FcbDelete(xfcb FAR * lpXfcb); +UBYTE FcbRename(xfcb FAR * lpXfcb); +UBYTE FcbClose(xfcb FAR * lpXfcb); +void FcbCloseAll(void); +UBYTE FcbFindFirstNext(xfcb FAR * lpXfcb, BOOL First); /* ioctl.c */ -COUNT DosDevIOctl(iregs FAR * r); +COUNT DosDevIOctl(lregs * r); /* memmgr.c */ seg far2para(VOID FAR * p); seg long2para(ULONG size); VOID FAR *add_far(VOID FAR * fp, ULONG off); -void FAR *adjust_far(const void FAR * fp); +VOID FAR *adjust_far(const void FAR * fp); COUNT DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize); COUNT DosMemLargest(UWORD FAR * size); @@ -242,12 +231,16 @@ VOID DosUmbLink(BYTE n); VOID mcb_print(mcb FAR * mcbp); /* misc.c */ -VOID ASMCFUNC strcpy(REG BYTE * d, REG const BYTE * s); -VOID ASMCFUNC fmemcpy(REG VOID FAR * d, REG const VOID FAR * s, REG COUNT n); -VOID ASMCFUNC fstrcpy(REG BYTE FAR * d, REG const BYTE FAR * s); -void ASMCFUNC memcpy(REG void *d, REG const VOID * s, REG COUNT n); -void ASMCFUNC fmemset(REG VOID FAR * s, REG int ch, REG COUNT n); -void ASMCFUNC memset(REG VOID * s, REG int ch, REG COUNT n); +char * ASMCFUNC strcpy(char * d, const char * s); +void ASMCFUNC fmemcpyBack(void FAR * d, const void FAR * s, size_t n); +void ASMCFUNC fmemcpy(void FAR * d, const void FAR * s, size_t n); +void ASMCFUNC fstrcpy(char FAR * d, const char FAR * s); +void * ASMCFUNC memcpy(void *d, const void * s, size_t n); +void ASMCFUNC fmemset(void FAR * s, int ch, size_t n); +void * ASMCFUNC memset(void * s, int ch, size_t n); + +int ASMCFUNC memcmp(const void *m1, const void *m2, size_t n); +int ASMCFUNC fmemcmp(const void FAR *m1, const void FAR *m2, size_t n); /* lfnapi.c */ COUNT lfn_allocate_inode(VOID); @@ -279,27 +272,29 @@ COUNT DosGetCountryInformation(UWORD cntry, VOID FAR * buf); #ifndef DosSetCountry COUNT DosSetCountry(UWORD cntry); #endif -COUNT DosGetCodepage(UWORD FAR * actCP, UWORD FAR * sysCP); +COUNT DosGetCodepage(UWORD * actCP, UWORD * sysCP); COUNT DosSetCodepage(UWORD actCP, UWORD sysCP); UWORD ASMCFUNC syscall_MUX14(DIRECT_IREGS); /* prf.c */ VOID put_console(COUNT c); -WORD CDECL printf(CONST BYTE * fmt, ...); -WORD CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...); +int CDECL printf(CONST BYTE * fmt, ...); +int CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...); VOID hexd(char *title, VOID FAR * p, COUNT numBytes); /* strings.c */ -COUNT ASMCFUNC strlen(REG BYTE * s); -COUNT ASMCFUNC fstrlen(REG BYTE FAR * s); -VOID ASMCFUNC _fstrcpy(REG BYTE FAR * d, REG BYTE FAR * s); -VOID ASMCFUNC strncpy(REG BYTE * d, REG BYTE * s, COUNT l); -COUNT ASMCFUNC strcmp(REG BYTE * d, REG BYTE * s); -COUNT ASMCFUNC fstrcmp(REG BYTE FAR * d, REG BYTE FAR * s); -COUNT ASMCFUNC fstrncmp(REG BYTE FAR * d, REG BYTE FAR * s, COUNT l); -COUNT ASMCFUNC strncmp(REG BYTE * d, REG BYTE * s, COUNT l); -void ASMCFUNC fstrncpy(REG BYTE FAR * d, REG BYTE FAR * s, COUNT l); -BYTE * ASMCFUNC strchr(const BYTE * s, BYTE c); +size_t ASMCFUNC strlen(const char * s); +size_t ASMCFUNC fstrlen(const char FAR * s); +char FAR * ASMCFUNC _fstrcpy(char FAR * d, const char FAR * s); +char * ASMCFUNC strncpy(char * d, const char * s, size_t l); +int ASMCFUNC strcmp(const char * d, const char * s); +int ASMCFUNC fstrcmp(const char FAR * d, const char FAR * s); +int ASMCFUNC fstrncmp(const char FAR * d, const char FAR * s, size_t l); +int ASMCFUNC strncmp(const char * d, const char * s, size_t l); +void ASMCFUNC fstrncpy(char FAR * d, const char FAR * s, size_t l); +char * ASMCFUNC strchr(const char * s, int c); +char FAR * ASMCFUNC fstrchr(const char FAR * s, int c); +void FAR * ASMCFUNC fmemchr(const void FAR * s, int c, size_t n); /* sysclk.c */ COUNT BcdToByte(COUNT x); @@ -309,19 +304,17 @@ LONG WordToBcd(BYTE * x, UWORD * mon, UWORD * day, UWORD * yr); /* syspack.c */ #ifdef NONNATIVE -VOID getdirent(BYTE FAR * vp, struct dirent FAR * dp); -VOID putdirent(struct dirent FAR * dp, BYTE FAR * vp); +VOID getdirent(UBYTE FAR * vp, struct dirent FAR * dp); +VOID putdirent(struct dirent FAR * dp, UBYTE FAR * vp); #else #define getdirent(vp, dp) fmemcpy(dp, vp, sizeof(struct dirent)) #define putdirent(dp, vp) fmemcpy(vp, dp, sizeof(struct dirent)) #endif /* systime.c */ -VOID DosGetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, - BYTE FAR * hdp); +VOID DosGetTime(UBYTE * hp, UBYTE * mp, UBYTE * sp, UBYTE * hdp); COUNT DosSetTime(BYTE h, BYTE m, BYTE s, BYTE hd); -VOID DosGetDate(BYTE FAR * wdp, BYTE FAR * mp, BYTE FAR * mdp, - COUNT FAR * yp); +VOID DosGetDate(UBYTE * wdp, UBYTE * mp, UBYTE * mdp, UWORD * yp); COUNT DosSetDate(UWORD Month, UWORD DayOfMonth, UWORD Year); const UWORD *is_leap_year_monthdays(UWORD year); @@ -337,8 +330,8 @@ VOID InitPSP(VOID); /* newstuff.c */ int SetJFTSize(UWORD nHandles); int DosMkTmp(BYTE FAR * pathname, UWORD attr); -COUNT get_verify_drive(char FAR * src); -COUNT truename(char FAR * src, char FAR * dest, COUNT t); +COUNT get_verify_drive(const char FAR * src); +COUNT truename(const char FAR * src, char * dest, COUNT t); /* network.c */ COUNT ASMCFUNC remote_doredirect(UWORD b, UCOUNT n, UWORD d, VOID FAR * s, @@ -358,6 +351,7 @@ COUNT ASMCFUNC remote_findnext(VOID FAR * s); COUNT ASMCFUNC remote_getfattr(VOID); COUNT ASMCFUNC remote_getfree(VOID FAR * s, VOID * d); COUNT ASMCFUNC remote_open(sft FAR * s, COUNT mode); +int ASMCFUNC remote_extopen(sft FAR * s, unsigned attr); LONG ASMCFUNC remote_lseek(sft FAR * s, LONG new_pos); UCOUNT ASMCFUNC remote_read(sft FAR * s, UCOUNT n, COUNT * err); UCOUNT ASMCFUNC remote_write(sft FAR * s, UCOUNT n, COUNT * err); @@ -366,7 +360,7 @@ COUNT ASMCFUNC remote_setfattr(COUNT attr); COUNT ASMCFUNC remote_printredir(UCOUNT dx, UCOUNT ax); COUNT ASMCFUNC remote_commit(sft FAR * s); COUNT ASMCFUNC remote_close(sft FAR * s); -COUNT ASMCFUNC QRemote_Fn(char FAR * s, char FAR * d); +COUNT ASMCFUNC QRemote_Fn(char FAR * d, const char FAR * s); UWORD get_machine_name(BYTE FAR * netname); VOID set_machine_name(BYTE FAR * netname, UWORD name_num); diff --git a/kernel/systime.c b/kernel/systime.c index 4dd90c2..a73711b 100644 --- a/kernel/systime.c +++ b/kernel/systime.c @@ -74,16 +74,10 @@ UWORD DaysFromYearMonthDay(UWORD Year, UWORD Month, UWORD DayOfMonth) /* common - call the clock driver */ void ExecuteClockDriverRequest(BYTE command) { - ClkReqHdr.r_length = sizeof(request); - ClkReqHdr.r_command = command; - ClkReqHdr.r_count = sizeof(struct ClockRecord); - ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); - ClkReqHdr.r_status = 0; - execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); + BinaryCharIO(clock, sizeof(struct ClockRecord), &ClkRecord, command, &UnusedRetVal); } -VOID DosGetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, - BYTE FAR * hdp) +VOID DosGetTime(UBYTE * hp, UBYTE * mp, UBYTE * sp, UBYTE * hdp) { ExecuteClockDriverRequest(C_INPUT); @@ -113,9 +107,7 @@ COUNT DosSetTime(BYTE h, BYTE m, BYTE s, BYTE hd) return SUCCESS; } -VOID DosGetDate(wdp, mp, mdp, yp) -BYTE FAR *wdp, FAR * mp, FAR * mdp; -COUNT FAR *yp; +VOID DosGetDate(UBYTE *wdp, UBYTE *mp, UBYTE *mdp, UWORD *yp) { UWORD c; const UWORD *pdays; diff --git a/kernel/task.c b/kernel/task.c index 4bd5c7f..3fcc09b 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -461,7 +461,6 @@ COUNT DosComLoader(BYTE FAR * namep, exec_blk * exp, COUNT mode, COUNT fd) /* Now load the executable */ { BYTE FAR *sp; - ULONG tmp; if (mode == OVERLAY) /* memory already allocated */ sp = MK_FP(mem, 0); @@ -472,7 +471,7 @@ COUNT DosComLoader(BYTE FAR * namep, exec_blk * exp, COUNT mode, COUNT fd) -- 1999/04/21 ska */ /* rewind to start */ - DosSeek(fd, 0, 0, &tmp); + DosSeek(fd, 0, 0); /* read everything, but at most 64K - sizeof(PSP) */ DosRead(fd, 0xff00, sp, &UnusedRetVal); DosClose(fd); @@ -552,7 +551,7 @@ VOID return_user(void) COUNT DosExeLoader(BYTE FAR * namep, exec_blk * exp, COUNT mode, COUNT fd) { UWORD mem, env, start_seg, asize = 0; - ULONG exe_size, tmp; + ULONG exe_size; { ULONG image_size; ULONG image_offset; @@ -646,8 +645,7 @@ COUNT DosExeLoader(BYTE FAR * namep, exec_blk * exp, COUNT mode, COUNT fd) /* Now load the executable */ /* offset to start of image */ - DosSeek(fd, image_offset, 0, &tmp); - if (tmp != image_offset) + if (DosSeek(fd, image_offset, 0) != image_offset) { if (mode != OVERLAY) { @@ -696,9 +694,8 @@ COUNT DosExeLoader(BYTE FAR * namep, exec_blk * exp, COUNT mode, COUNT fd) COUNT i; UWORD reloc[2]; seg FAR *spot; - ULONG tmp; - DosSeek(fd, ExeHeader.exRelocTable, 0, &tmp); + DosSeek(fd, ExeHeader.exRelocTable, 0); for (i = 0; i < ExeHeader.exRelocItems; i++) { if (DosRead @@ -765,11 +762,7 @@ COUNT DosExec(COUNT mode, exec_blk FAR * ep, BYTE FAR * lp) /* If file not found - free ram and return error */ if (IsDevice(lp) || /* we don't want to execute C:>NUL */ -#if 0 (fd = (short)DosOpen(lp, O_LEGACY | O_OPEN | O_RDONLY, 0)) < 0) -#else - (fd = (short)DosOpen(lp, 0)) < 0) -#endif { return DE_FILENOTFND; } diff --git a/sys/makefile b/sys/makefile index bcb815a..7acff45 100644 --- a/sys/makefile +++ b/sys/makefile @@ -20,7 +20,7 @@ SYS_EXE_dependencies = \ production: bin2c.com ..\bin\sys.com bin2c.com: bin2c.c - $(CL) $(CFLAGST) $(TINY) bin2c.c + $(CL) $(CFLAGS) $(TINY) bin2c.c ..\bin\sys.com: sys.com copy sys.com ..\bin diff --git a/sys/sys.c b/sys/sys.c index 45f243d..9046ce0 100644 --- a/sys/sys.c +++ b/sys/sys.c @@ -622,8 +622,7 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both) temp = bs32->sysFatSecMask + 1; for (bs32->sysFatSecShift = 0; temp != 1; bs32->sysFatSecShift++, temp >>= 1) ; - - /* use fixed drive for A:, B: and DL otherwise */ + /* put 0 for A: or B: (force booting from A:), otherwise use DL */ bs32->bsDriveNumber = drive < 2 ? 0 : 0xff; } #ifdef DEBUG @@ -659,9 +658,8 @@ VOID put_boot(COUNT drive, BYTE * bsFile, BOOL both) /* sector data starts on */ temp = temp + bs->sysRootDirSecs; bs->sysDataStart = temp; - - /* use fixed BIOS drive 0 for A:, B: and DL otherwise */ - bs32->bsDriveNumber = drive < 2 ? 0 : 0xff; + /* put 0 for A: or B: (force booting from A:), otherwise use DL */ + bs->bsDriveNumber = drive < 2 ? 0 : 0xff; } #ifdef DEBUG