/****************************************************************/ /* */ /* dosfns.c */ /* */ /* DOS functions */ /* */ /* Copyright (c) 1995 */ /* Pasquale J. Villani */ /* All Rights Reserved */ /* */ /* This file is part of DOS-C. */ /* */ /* DOS-C is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version */ /* 2, or (at your option) any later version. */ /* */ /* DOS-C is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ /* the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public */ /* License along with DOS-C; see the file COPYING. If not, */ /* write to the Free Software Foundation, 675 Mass Ave, */ /* Cambridge, MA 02139, USA. */ /****************************************************************/ #include "../../hdr/portab.h" /* $Logfile: C:/dos-c/src/fs/dosfns.c_v $ */ #ifndef IPL static BYTE *dosfnsRcsId = "$Header: C:/dos-c/src/fs/dosfns.c_v 1.2 01 Sep 1995 17:48:48 patv $"; #endif /* * $Log: C:/dos-c/src/fs/dosfns.c_v $ * * Rev 1.2 01 Sep 1995 17:48:48 patv * First GPL release. * * Rev 1.1 30 Jul 1995 20:50:24 patv * Eliminated version strings in ipl * * Rev 1.0 02 Jul 1995 8:04:20 patv * Initial revision. */ #include "globals.h" #ifdef PROTO BOOL check_break(VOID); sft FAR *get_sft(COUNT); WORD get_free_hndl(VOID); sft FAR *get_free_sft(WORD FAR *); BYTE FAR *get_root(BYTE FAR *); BOOL cmatch(COUNT, COUNT, COUNT); BOOL fnmatch(BYTE FAR *, BYTE FAR *, COUNT, COUNT); #else BOOL check_break(); sft FAR *get_sft(); WORD get_free_hndl(); sft FAR *get_free_sft(); BYTE FAR *get_root(); BOOL cmatch(); BOOL fnmatch(); #endif BOOL check_break (void) { if(break_ena && con_break()) { handle_break(); /* shouldn't return, but in case... */ return TRUE; } else return FALSE; } static sft FAR *get_sft(hndl) COUNT hndl; { psp FAR *p = MK_FP(cu_psp,0); WORD sys_idx; sfttbl FAR *sp; /* Get the SFT block that contains the SFT */ sys_idx = p -> ps_filetab[hndl]; for(sp = sfthead; sp != (sfttbl FAR *)-1; sp = sp -> sftt_next) { if(sys_idx < sp -> sftt_count) break; else sys_idx -= sp -> sftt_count; } /* If not found, return an error */ if(sp == (sfttbl FAR *)-1) return (sft FAR *)-1; /* finally, point to the right entry */ return (sft FAR *)&(sp -> sftt_table[sys_idx]); } UCOUNT DosRead (COUNT hndl, UCOUNT n, BYTE FAR *bp, COUNT FAR *err) { sft FAR *s; WORD sys_idx; sfttbl FAR *sp; UCOUNT ReadCount; /* Test that the handle is valid */ if(hndl < 0) { *err = DE_INVLDHNDL; return 0; } /* Get the SFT block that contains the SFT */ if((s = get_sft(hndl)) == (sft FAR *)-1) { *err = DE_INVLDHNDL; return 0; } /* If not open or write permission - exit */ if(s -> sft_count == 0 || (s -> sft_mode & SFT_MWRITE)) { *err = DE_INVLDACC; return 0; } /* Do a device read if device */ if(s -> sft_flags & SFT_FDEVICE) { request rq; /* 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(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) { REG i; BYTE buff[FNAME_SIZE+1]; fbcopy(s -> sft_name, (BYTE FAR *)buff, FNAME_SIZE); buff[FNAME_SIZE+1] = 0; for(i = FNAME_SIZE; i > 0; i--) if(buff[i] == ' ') buff[i] = 0; else break; char_error(&rq, buff); } else { *err = SUCCESS; return rq.r_count; } } else if(s -> sft_flags & SFT_FSTDIN) { if(!check_break()) { kb_buf.kb_size = LINESIZE - 1; kb_buf.kb_count = 0; sti((keyboard FAR *)&kb_buf); fbcopy((BYTE FAR *)kb_buf.kb_buf, bp, kb_buf.kb_count); *err = SUCCESS; return kb_buf.kb_count; } else { *err = SUCCESS; return 0; } } else { if(!check_break()) { *bp = _sti(); *err = SUCCESS; return 1; } else { *err = SUCCESS; return 0; } } } else /* a block read */ { if(!check_break()) { COUNT rc; ReadCount = rdwrblock(s -> sft_status, bp, n, XFR_READ, &rc); if(rc != SUCCESS) { *err = rc; return 0; } else { *err = SUCCESS; return ReadCount; } } else { *err = SUCCESS; return 0; } } *err = SUCCESS; return 0; } UCOUNT DosWrite (COUNT hndl, UCOUNT n, BYTE FAR *bp, COUNT FAR *err) { sft FAR *s; WORD sys_idx; sfttbl FAR *sp; UCOUNT ReadCount; /* Test that the handle is valid */ if(hndl < 0) { *err = DE_INVLDHNDL; return 0; } /* Get the SFT block that contains the SFT */ if((s = get_sft(hndl)) == (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; } /* 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) { REG i; BYTE buff[FNAME_SIZE+1]; fbcopy(s -> sft_name, (BYTE FAR *)buff, FNAME_SIZE); buff[FNAME_SIZE+1] = 0; for(i = FNAME_SIZE; i > 0; i--) if(buff[i] == ' ') buff[i] = 0; else break; char_error(&rq, buff); } else { *err = SUCCESS; return rq.r_count; } } else if(s -> sft_flags & SFT_FSTDOUT) { REG WORD c, cnt = n, xfer = 0; while((cnt-- > 0) && ((c = *bp++) != CTL_Z) && !check_break()) { switch(c) { case LF: case CR: sto(c); break; default: mod_sto(c); break; } ++xfer; } *err = SUCCESS; return xfer; } else { REG c, cnt = n, xfer = 0; while(cnt-- && (*bp != CTL_Z) && !check_break()) { 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) { REG i; BYTE buff[FNAME_SIZE+1]; fbcopy(s -> sft_name, (BYTE FAR *)buff, FNAME_SIZE); buff[FNAME_SIZE+1] = 0; for(i = FNAME_SIZE; i > 0; i--) if(buff[i] == ' ') buff[i] = 0; else break; char_error(&rq, buff); } ++xfer; } *err = SUCCESS; return xfer; } } else /* a block write */ { if(!check_break()) { COUNT rc; ReadCount = rdwrblock(s -> sft_status, bp, n, XFR_WRITE, &rc); if(rc < SUCCESS) { *err = rc; return 0; } else { *err = SUCCESS; return ReadCount; } } else { *err = SUCCESS; return 0; } } *err = SUCCESS; return 0; } COUNT DosSeek (COUNT hndl, LONG new_pos, COUNT mode, ULONG *set_pos) { sft FAR *s; /* Test for invalid mode */ if(mode < 0 || mode > 2) return DE_INVLDFUNC; /* Test that the handle is valid */ if(hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if((s = get_sft(hndl)) == (sft FAR *)-1) return DE_INVLDHNDL; /* Do special return for character devices */ if(s -> sft_flags & SFT_FDEVICE) { *set_pos = 0l; return SUCCESS; } else { *set_pos = dos_lseek(s -> sft_status, new_pos, mode); if((LONG)*set_pos < 0) return (int)*set_pos; else return SUCCESS; } } static WORD get_free_hndl (void) { psp FAR *p = MK_FP(cu_psp,0); WORD hndl; for(hndl = 0; hndl < p -> ps_maxfiles; hndl++) { if(p -> ps_filetab[hndl] == 0xff) return hndl; } return 0xff; } static sft FAR *get_free_sft(sft_idx) WORD FAR *sft_idx; { WORD sys_idx = 0; sfttbl FAR *sp; /* Get the SFT block that contains the SFT */ for(sp = sfthead; sp != (sfttbl FAR *)-1; sp = sp -> sftt_next) { REG WORD i; for(i = 0; i < sp -> sftt_count; i++) { if(sp -> sftt_table[i].sft_count == 0) { *sft_idx = sys_idx + i; return (sft FAR *)&sp -> sftt_table[sys_idx + i]; } } sys_idx += i; } /* If not found, return an error */ return (sft FAR *)-1; } static BYTE FAR * get_root (BYTE FAR *fname) { BYTE FAR *froot; REG WORD length; /* find the end */ for(length = 0, froot = fname; !froot != '\0'; ++froot) ++length; /* now back up to first path seperator or start */ for(--froot; length > 0 && !(*froot == '/' || *froot == '\\'); --froot) ; return ++froot; } /* Ascii only file name match routines */ static BOOL cmatch (COUNT s, COUNT d, COUNT mode) { if(s >= 'a' && s <= 'z') s -= 'a' - 'A'; if(d >= 'a' && d <= 'z') d -= 'a' - 'A'; if(mode && s == '?' && (d >= 'A' && s <= 'Z')) return TRUE; return s == d; } static BOOL fnmatch (BYTE FAR *s, BYTE FAR *d, COUNT n, COUNT mode) { while(n--) { if(!cmatch(*s++, *d++, mode)) return FALSE; } return TRUE; } #ifndef IPL COUNT DosCreat (BYTE FAR *fname, COUNT attrib) { psp FAR *p = MK_FP(cu_psp,0); WORD hndl, sft_idx; sft FAR *sftp; struct dhdr FAR *dhp; BYTE FAR *froot; BYTE buff[FNAME_SIZE+FEXT_SIZE]; WORD i; /* get a free handle */ if((hndl = get_free_hndl()) == 0xff) return DE_TOOMANY; /* now get a free system file table entry */ if((sftp = get_free_sft((WORD FAR *)&sft_idx)) == (sft FAR *)-1) return DE_TOOMANY; /* check for a device */ froot = get_root(fname); for(i = 0; i < FNAME_SIZE; i++) { if(*froot != '\0' && *froot != '.') buff[i] = *froot++; else break; } for( ; i < FNAME_SIZE; i++) buff[i] = ' '; /* if we have an extension, can't be a device */ if(*froot != '.'); { for(dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp -> dh_next) { if(fnmatch((BYTE FAR *)buff, (BYTE FAR *)dhp -> dh_name, FNAME_SIZE, FALSE)) { sftp -> sft_count += 1; sftp -> sft_mode = SFT_MRDWR; sftp -> sft_attrib = attrib; sftp -> sft_flags = (dhp -> dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF; sftp -> sft_psp = cu_psp; fbcopy((BYTE FAR *)buff, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE); sftp -> sft_dev = dhp; p -> ps_filetab[hndl] = sft_idx; return hndl; } } } sftp -> sft_status = dos_creat(fname, attrib); if(sftp -> sft_status >= 0) { p -> ps_filetab[hndl] = sft_idx; sftp -> sft_count += 1; sftp -> sft_mode = SFT_MRDWR; sftp -> sft_attrib = attrib; sftp -> sft_flags = 0; sftp -> sft_psp = cu_psp; fbcopy((BYTE FAR *)buff, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE); return hndl; } else return sftp -> sft_status; } #endif COUNT CloneHandle (COUNT hndl) { sft FAR *sftp; /* now get the system file table entry */ if((sftp = get_sft(hndl)) == (sft FAR *)-1) 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. */ sftp -> sft_count += 1; return hndl; } COUNT DosDup (COUNT Handle) { psp FAR *p = MK_FP(cu_psp,0); COUNT NewHandle; sft FAR *Sftp; /* Get the SFT block that contains the SFT */ if((Sftp = get_sft(Handle)) == (sft FAR *)-1) return DE_INVLDACC; /* If not open - exit */ if(Sftp -> sft_count <= 0) return DE_INVLDACC; /* now get a free handle */ if((NewHandle = get_free_hndl()) == 0xff) return DE_TOOMANY; /* If everything looks ok, bump it up. */ if((Sftp -> sft_flags & SFT_FDEVICE) || (Sftp -> sft_status >= 0)) { p -> ps_filetab[NewHandle] = p -> ps_filetab[Handle]; Sftp -> sft_count += 1; return NewHandle; } else return DE_INVLDACC; } COUNT DosForceDup (COUNT OldHandle, COUNT NewHandle) { psp FAR *p = MK_FP(cu_psp,0); sft FAR *Sftp; /* Get the SFT block that contains the SFT */ if((Sftp = get_sft(OldHandle)) == (sft FAR *)-1) return DE_INVLDACC; /* If not open - exit */ if(Sftp -> sft_count <= 0) return DE_INVLDACC; /* now close the new handle if it's open */ if(p -> ps_filetab[NewHandle] != 0xff) { COUNT ret; if((ret = DosClose(NewHandle)) != SUCCESS) return ret; } /* If everything looks ok, bump it up. */ if((Sftp -> sft_flags & SFT_FDEVICE) || (Sftp -> sft_status >= 0)) { p -> ps_filetab[NewHandle] = p -> ps_filetab[OldHandle]; Sftp -> sft_count += 1; return SUCCESS; } else return DE_INVLDACC; } COUNT DosOpen (BYTE FAR *fname, COUNT mode) { psp FAR *p = MK_FP(cu_psp,0); WORD hndl, sft_idx; sft FAR *sftp; struct dhdr FAR *dhp; BYTE FAR *froot; BYTE buff[FNAME_SIZE+FEXT_SIZE]; WORD i; /* test if mode is in range */ if((mode & SFT_OMASK) != 0) return DE_INVLDACC; /* get a free handle */ if((hndl = get_free_hndl()) == 0xff) return DE_TOOMANY; /* now het a free system file table entry */ if((sftp = get_free_sft((WORD FAR *)&sft_idx)) == (sft FAR *)-1) return DE_TOOMANY; /* check for a device */ froot = get_root(fname); for(i = 0; i < FNAME_SIZE; i++) { if(*froot != '\0' && *froot != '.') buff[i] = *froot++; else break; } for( ; i < FNAME_SIZE; i++) buff[i] = ' '; /* if we have an extension, can't be a device */ if(*froot != '.'); { for(dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp -> dh_next) { if(fnmatch((BYTE FAR *)buff, (BYTE FAR *)dhp -> dh_name, FNAME_SIZE, FALSE)) { sftp -> sft_count += 1; sftp -> sft_mode = mode; sftp -> sft_attrib = 0; sftp -> sft_flags = (dhp -> dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF; sftp -> sft_psp = cu_psp; fbcopy((BYTE FAR *)buff, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE); sftp -> sft_dev = dhp; p -> ps_filetab[hndl] = sft_idx; return hndl; } } } sftp -> sft_status = dos_open(fname, mode); if(sftp -> sft_status >= 0) { p -> ps_filetab[hndl] = sft_idx; sftp -> sft_count += 1; sftp -> sft_mode = mode; sftp -> sft_attrib = 0; sftp -> sft_flags = 0; sftp -> sft_psp = cu_psp; fbcopy((BYTE FAR *)buff, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE); return hndl; } else return sftp -> sft_status; } COUNT DosClose (COUNT hndl) { psp FAR *p = MK_FP(cu_psp,0); sft FAR *s; /* Test that the handle is valid */ if(hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if((s = get_sft(hndl)) == (sft FAR *)-1) return DE_INVLDHNDL; /* If this is not opened another error */ if(s -> sft_count == 0) return DE_ACCESS; /* now just drop the count if a device, else */ /* call file system handler */ if(s -> sft_flags & SFT_FDEVICE) { p -> ps_filetab[hndl] = 0xff; s -> sft_count -= 1; return SUCCESS; } else { p -> ps_filetab[hndl] = 0xff; s -> sft_count -= 1; if(s -> sft_count > 0) return SUCCESS; else return dos_close(s -> sft_status); } } VOID DosGetFree (COUNT drive, COUNT FAR *spc, COUNT FAR *navc, COUNT FAR *bps, COUNT FAR *nc) { struct dpb *dpbp; /* first check for valid drive */ if(drive < 0 || drive > NDEVS) { *spc = -1; return; } /* next - "log" in the drive */ drive = (drive == 0 ? default_drive : drive - 1); dpbp = &blk_devices[drive]; ++(dpbp -> dpb_count); dpbp -> dpb_flags = -1; if((media_check(dpbp) < 0) || (dpbp -> dpb_count <= 0)) { *spc = -1; return; } /* get the data vailable from dpb */ *nc = (dpbp -> dpb_size - dpbp -> dpb_data + 1) / dpbp -> dpb_clssize; *spc = dpbp -> dpb_clssize; *bps = dpbp -> dpb_secsize; /* now tell fs to give us free cluster */ /* count */ *navc = dos_free(dpbp); --(dpbp -> dpb_count); } COUNT DosGetCuDir (COUNT drive, BYTE FAR *s) { REG struct dpb *dpbp; /* first check for valid drive */ if(drive < 0 || drive > NDEVS) return DE_INVLDDRV; /* next - "log" in the drive */ drive = (drive == 0 ? default_drive : drive - 1); dpbp = &blk_devices[drive]; dpbp -> dpb_flags = -1; ++(dpbp -> dpb_count); if((media_check(dpbp) < 0) || (dpbp -> dpb_count <= 0)) return DE_INVLDDRV; /* now get fs to give current */ /* directory */ dos_pwd(dpbp, s); --(dpbp -> dpb_count); return SUCCESS; } COUNT DosChangeDir (BYTE FAR *s) { REG struct dpb *dpbp; REG COUNT drive; struct f_node *fp; COUNT ret; /* test for path existance from fs */ if((fp = dir_open((BYTE FAR *)s)) == (struct f_node *)0) return DE_PATHNOTFND; else dir_close(fp); /* Parse and extract drive */ if(*(s + 1) == ':') { drive = *s++ - '@'; ++s; } else drive = 0; /* first check for valid drive */ if(drive < 0 || drive > NDEVS) return DE_INVLDDRV; /* next - "log" in the drive */ drive = (drive == 0 ? default_drive : drive - 1); dpbp = &blk_devices[drive]; ++(dpbp -> dpb_count); dpbp -> dpb_flags = -1; if((media_check(dpbp) < 0) || (dpbp -> dpb_count <= 0)) return DE_INVLDDRV; /* now get fs to change to new */ /* directory */ ret = dos_cd(dpbp, s); --(dpbp -> dpb_count); return ret; } COUNT DosFindFirst (UCOUNT attr, BYTE FAR *name) { return dos_findfirst(attr, name); } COUNT DosFindNext (void) { return dos_findnext(); } #ifndef IPL COUNT DosGetFtime(hndl, dp, tp) COUNT hndl; date FAR *dp; time FAR *tp; { sft FAR *s; sfttbl FAR *sp; /* Test that the handle is valid */ if(hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if((s = get_sft(hndl)) == (sft FAR *)-1) return DE_INVLDHNDL; /* If this is not opened another error */ if(s -> sft_count == 0) return DE_ACCESS; /* call file system handler */ return dos_getftime(s -> sft_status, dp, tp); } COUNT DosSetFtime(hndl, dp, tp) COUNT hndl; date FAR *dp; time FAR *tp; { sft FAR *s; sfttbl FAR *sp; /* Test that the handle is valid */ if(hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if((s = get_sft(hndl)) == (sft FAR *)-1) return DE_INVLDHNDL; /* If this is not opened another error */ if(s -> sft_count == 0) return DE_ACCESS; /* call file system handler */ return dos_setftime(s -> sft_status, dp, tp); } #endif COUNT DosGetFattr (BYTE FAR *name, UWORD FAR *attrp) { return dos_getfattr(name, attrp); } COUNT DosSetFattr (BYTE FAR *name, UWORD FAR *attrp) { return dos_setfattr(name, attrp); }