diff --git a/kernel/dosfns.c b/kernel/dosfns.c index 38c23b8..75f927b 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -33,7 +33,13 @@ static BYTE *dosfnsRcsId = "$Id$"; #endif /* + * + * /// Added SHARE support. 2000/09/04 Ron Cemer + * * $Log$ + * Revision 1.9 2000/10/29 23:51:56 jimtabor + * Adding Share Support by Ron Cemer + * * Revision 1.8 2000/08/06 05:50:17 jimtabor * Add new files and update cvs with patches and changes * @@ -150,6 +156,61 @@ BOOL cmatch(COUNT, COUNT, COUNT); struct f_node FAR *xlt_fd(COUNT); + +/* /// Added for SHARE. - Ron Cemer */ + +int share_installed = 0; + + /* DOS calls this to see if it's okay to open the file. + Returns a file_table entry number to use (>= 0) if okay + to open. Otherwise returns < 0 and may generate a critical + 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 */ + 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... */ + + /* DOS calls this to record the fact that it has successfully + closed a file, or the fact that the open for this file failed. */ +static void share_close_file + (int fileno); /* file_table entry number */ + + /* DOS calls this to determine whether it can access (read or + write) a specific section of a file. We call it internally + from lock_unlock (only when locking) to see if any portion + of the requested region is already locked. If pspseg is zero, + then it matches any pspseg in the lock table. Otherwise, only + locks which DO NOT belong to pspseg will be considered. + Returns zero if okay to access or lock (no portion of the + region is already locked). Otherwise returns non-zero and + generates a critical error (if allowcriter is non-zero). + If non-zero is returned, it is the negated return value for + the DOS call. */ +static int share_access_check + (unsigned short pspseg,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to access */ + int allowcriter); /* allow a critical error to be generated */ + + /* DOS calls this to lock or unlock a specific section of a file. + Returns zero if successfully locked or unlocked. Otherwise + returns non-zero. + If the return value is non-zero, it is the negated error + return code for the DOS 0x5c call. */ +static int share_lock_unlock + (unsigned short pspseg,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to lock or unlock */ + int unlock); /* non-zero to unlock; zero to lock */ + +/* /// End of additions for SHARE. - Ron Cemer */ + + static VOID DosGetFile(BYTE FAR * lpszPath, BYTE FAR * lpszDosFileName) { BYTE szLclName[FNAME_SIZE + 1]; @@ -292,6 +353,23 @@ UCOUNT GenericRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err, { COUNT rc; + /* /// 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 = readblock(s->sft_status, bp, n, &rc); if (rc != SUCCESS) { @@ -482,6 +560,23 @@ UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err) { COUNT rc; + /* /// 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 = writeblock(s->sft_status, bp, n, &rc); if (rc < SUCCESS) { @@ -674,6 +769,8 @@ COUNT DosCreat(BYTE FAR * fname, COUNT attrib) if ((sftp = get_free_sft((WORD FAR *) & sft_idx)) == (sft FAR *) - 1) return DE_TOOMANY; + sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */ + /* check for a device */ dhp = IsDevice(fname); if ( dhp ) @@ -712,6 +809,17 @@ COUNT DosCreat(BYTE FAR * fname, COUNT attrib) return result; } +/* /// Added for SHARE. - Ron Cemer */ + if (IsShareInstalled()) { + if ((sftp->sft_shroff = share_open_check + ((char far *)PriPathName, + cu_psp, + 0x02, /* read-write */ + 0)) < 0) /* compatibility mode */ + return sftp->sft_shroff; + } +/* /// End of additions for SHARE. - Ron Cemer */ + sftp->sft_status = dos_creat(fname, attrib); if (sftp->sft_status >= 0) { @@ -723,9 +831,15 @@ COUNT DosCreat(BYTE FAR * fname, COUNT attrib) sftp->sft_psp = cu_psp; DosGetFile(fname, sftp->sft_name); return hndl; - } - else + } 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 CloneHandle(COUNT hndl) @@ -841,6 +955,8 @@ COUNT DosOpen(BYTE FAR * fname, COUNT mode) if ((sftp = get_free_sft((WORD FAR *) & sft_idx)) == (sft FAR *) - 1) return DE_TOOMANY; + sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */ + /* check for a device */ dhp = IsDevice(fname); if ( dhp ) @@ -880,6 +996,18 @@ COUNT DosOpen(BYTE FAR * fname, COUNT mode) } return result; } + +/* /// Added for SHARE. - Ron Cemer */ + if (IsShareInstalled()) { + if ((sftp->sft_shroff = share_open_check + ((char far *)PriPathName, + (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) @@ -903,9 +1031,15 @@ COUNT DosOpen(BYTE FAR * fname, COUNT mode) sftp->sft_psp = cu_psp; DosGetFile(fname, sftp->sft_name); return hndl; - } - else + } 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 DosClose(COUNT hndl) @@ -951,8 +1085,15 @@ COUNT DosClose(COUNT hndl) s->sft_count -= 1; if (s->sft_count > 0) return SUCCESS; - else + else { +/* /// Added for SHARE *** CURLY BRACES ADDED ALSO!!! ***. - Ron Cemer */ + if (IsShareInstalled()) { + if (s->sft_shroff >= 0) share_close_file(s->sft_shroff); + s->sft_shroff = -1; + } +/* /// End of additions for SHARE. - Ron Cemer */ return dos_close(s->sft_status); + } } } @@ -1382,6 +1523,30 @@ COUNT DosRmdir(BYTE FAR * dir) return result; } +/* /// Added for SHARE. - Ron Cemer */ + +COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock) +{ + sft FAR *s; + + /* Invalid function unless SHARE is installed. */ + if (!IsShareInstalled()) 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; + + /* Lock violation if this SFT entry does not support locking. */ + if (s->sft_shroff < 0) return DE_LOCK; + + /* Let SHARE do the work. */ + return share_lock_unlock(cu_psp, s->sft_shroff, pos, len, unlock); +} + +/* /// End of additions for SHARE. - Ron Cemer */ + /* * This seems to work well. */ @@ -1427,3 +1592,107 @@ struct dhdr FAR * IsDevice(BYTE FAR * fname) return (struct dhdr FAR *)0; } + +/* /// Added for SHARE. - Ron Cemer */ + +BOOL IsShareInstalled(void) { + if (!share_installed) { + iregs regs; + + regs.a.x = 0x1000; + intr(0x2f, ®s); + share_installed = ((regs.a.x & 0xff) == 0xff); + } + return share_installed; +} + + /* DOS calls this to see if it's okay to open the file. + Returns a file_table entry number to use (>= 0) if okay + to open. Otherwise returns < 0 and may generate a critical + 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 */ + 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... */ + iregs regs; + + regs.a.x = 0x10a0; + regs.ds = FP_SEG(filename); + regs.si = FP_OFF(filename); + regs.b.x = pspseg; + regs.c.x = openmode; + regs.d.x = sharemode; + intr(0x2f, ®s); + return (int)regs.a.x; +} + + /* DOS calls this to record the fact that it has successfully + closed a file, or the fact that the open for this file failed. */ +static void share_close_file + (int fileno) { /* file_table entry number */ + iregs regs; + + regs.a.x = 0x10a1; + regs.b.x = fileno; + intr(0x2f, ®s); +} + + /* DOS calls this to determine whether it can access (read or + write) a specific section of a file. We call it internally + from lock_unlock (only when locking) to see if any portion + of the requested region is already locked. If pspseg is zero, + then it matches any pspseg in the lock table. Otherwise, only + locks which DO NOT belong to pspseg will be considered. + Returns zero if okay to access or lock (no portion of the + region is already locked). Otherwise returns non-zero and + generates a critical error (if allowcriter is non-zero). + If non-zero is returned, it is the negated return value for + the DOS call. */ +static int share_access_check + (unsigned short pspseg,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to access */ + int allowcriter) { /* allow a critical error to be generated */ + iregs regs; + + regs.a.x = 0x10a2 | (allowcriter ? 0x01 : 0x00); + regs.b.x = pspseg; + regs.c.x = fileno; + regs.si = (unsigned short)((ofs >> 16) & 0xffffL); + regs.di = (unsigned short)(ofs & 0xffffL); + regs.es = (unsigned short)((len >> 16) & 0xffffL); + regs.d.x = (unsigned short)(len & 0xffffL); + intr(0x2f, ®s); + return (int)regs.a.x; +} + + /* DOS calls this to lock or unlock a specific section of a file. + Returns zero if successfully locked or unlocked. Otherwise + returns non-zero. + If the return value is non-zero, it is the negated error + return code for the DOS 0x5c call. */ +static int share_lock_unlock + (unsigned short pspseg,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to lock or unlock */ + int unlock) { /* non-zero to unlock; zero to lock */ + iregs regs; + + regs.a.x = 0x10a4 | (unlock ? 0x01 : 0x00); + regs.b.x = pspseg; + regs.c.x = fileno; + regs.si = (unsigned short)((ofs >> 16) & 0xffffL); + regs.di = (unsigned short)(ofs & 0xffffL); + regs.es = (unsigned short)((len >> 16) & 0xffffL); + regs.d.x = (unsigned short)(len & 0xffffL); + intr(0x2f, ®s); + return (int)regs.a.x; +} + +/* /// End of additions for SHARE. - Ron Cemer */ + diff --git a/kernel/fatfs.c b/kernel/fatfs.c index 481b525..c3bfa72 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -36,6 +36,9 @@ BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.8 2000/10/29 23:51:56 jimtabor + * Adding Share Support by Ron Cemer + * * Revision 1.7 2000/09/05 00:56:50 jimtabor * *** empty log message *** * @@ -199,6 +202,12 @@ struct f_node FAR *xlt_fd(COUNT); COUNT xlt_fnp(struct f_node FAR *); struct f_node FAR *split_path(BYTE FAR *, BYTE *, BYTE *, BYTE *); BOOL find_fname(struct f_node FAR *, BYTE *, BYTE *); + /* /// Added - Ron Cemer */ +static void merge_file_changes(struct f_node FAR *fnp, int collect); + /* /// Added - Ron Cemer */ +static int is_same_file(struct f_node FAR *fnp1, struct f_node FAR *fnp2); + /* /// Added - Ron Cemer */ +static int copy_file_changes(struct f_node FAR *src, struct f_node FAR *dst); date dos_getdate(VOID); time dos_gettime(VOID); BOOL find_free(struct f_node FAR *); @@ -255,13 +264,20 @@ COUNT dos_open(BYTE FAR * path, COUNT flag) fnp->f_highwater = fnp->f_dir.dir_size; fnp->f_back = LONG_LAST_CLUSTER; +/* /// Moved to below. - Ron Cemer fnp->f_cluster = fnp->f_dir.dir_start; - fnp->f_cluster_offset = 0l; /*JPP */ + fnp->f_cluster_offset = 0l; */ /*JPP */ fnp->f_flags.f_dmod = FALSE; fnp->f_flags.f_dnew = FALSE; fnp->f_flags.f_ddir = FALSE; + merge_file_changes(fnp, TRUE); /* /// Added - Ron Cemer */ + + /* /// Moved from above. - Ron Cemer */ + fnp->f_cluster = fnp->f_dir.dir_start; + fnp->f_cluster_offset = 0l; /*JPP */ + return xlt_fnp(fnp); } @@ -310,6 +326,7 @@ COUNT dos_close(COUNT fd) { fnp->f_dir.dir_size = fnp->f_highwater; fnp->f_flags.f_dmod = TRUE; + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ } fnp->f_flags.f_ddir = TRUE; @@ -421,6 +438,74 @@ static BOOL find_fname(struct f_node FAR * fnp, BYTE * fname, BYTE * fext) return found; } + /* /// Added - Ron Cemer */ + /* If more than one f_node has a file open, and a write + occurs, this function must be called to propagate the + results of that write to the other f_nodes which have + that file open. Note that this function only has an + effect if SHARE is installed. This is for compatibility + reasons, since DOS without SHARE does not share changes + between two or more open instances of the same file + unless these instances were generated by dup() or dup2(). */ +static void merge_file_changes(struct f_node FAR *fnp, int collect) { + struct f_node FAR *fnp2; + int i; + + if (!IsShareInstalled()) return; + for (i = 0; i < NFILES; i++) { + fnp2 = &f_nodes[i]; + if ( (fnp != (struct f_node FAR *)0) + && (fnp != fnp2) + && (fnp->f_count > 0) + && (is_same_file(fnp, fnp2)) ) { + if (collect) { + /* We're collecting file changes from any other + f_node which refers to this file. */ + if (fnp2->f_mode != RDONLY) { + fnp2->f_dir.dir_size = fnp2->f_highwater; + copy_file_changes(fnp2, fnp); + break; + } + } else { + /* We just made changes to this file, so we are + distributing these changes to the other f_nodes + which refer to this file. */ + if (fnp->f_mode != RDONLY) + fnp->f_dir.dir_size = fnp->f_highwater; + copy_file_changes(fnp, fnp2); + } + } + } +} + + /* /// Added - Ron Cemer */ +static int is_same_file(struct f_node FAR *fnp1, struct f_node FAR *fnp2) { + return + (fnp1->f_dpb->dpb_unit == fnp2->f_dpb->dpb_unit) + && (fnp1->f_dpb->dpb_subunit == fnp2->f_dpb->dpb_subunit) + && (fcmp + ((BYTE FAR *)fnp1->f_dir.dir_name, + (BYTE FAR *)fnp2->f_dir.dir_name, FNAME_SIZE)) + && (fcmp + ((BYTE FAR *)fnp1->f_dir.dir_ext, + (BYTE FAR *)fnp2->f_dir.dir_ext, FEXT_SIZE)) + && ((fnp1->f_dir.dir_attrib & D_VOLID) == 0) + && ((fnp2->f_dir.dir_attrib & D_VOLID) == 0) + && (fnp1->f_flags.f_dremote == fnp2->f_flags.f_dremote) + && (fnp1->f_diroff == fnp2->f_diroff) + && (fnp1->f_dirstart == fnp2->f_dirstart) + && (fnp1->f_dpb == fnp2->f_dpb); +} + + /* /// Added - Ron Cemer */ +static int copy_file_changes(struct f_node FAR *src, struct f_node FAR *dst) { + dst->f_highwater = src->f_highwater; + dst->f_dir.dir_start = src->f_dir.dir_start; + dst->f_dir.dir_size = src->f_dir.dir_size; + dst->f_dir.dir_date = src->f_dir.dir_date; + dst->f_dir.dir_time = src->f_dir.dir_time; +} + COUNT dos_creat(BYTE FAR * path, COUNT attrib) { REG struct f_node FAR *fnp; @@ -521,6 +606,8 @@ COUNT dos_creat(BYTE FAR * path, COUNT attrib) fnp->f_flags.f_dnew = FALSE; fnp->f_flags.f_ddir = FALSE; + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ + return xlt_fnp(fnp); } @@ -999,6 +1086,9 @@ BOOL dos_setfsize(COUNT fd, LONG size) /* Change the file size */ fnp->f_dir.dir_size = size; fnp->f_highwater = size; + + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ + return TRUE; } @@ -1633,13 +1723,13 @@ UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err) if (count == 0) { fnp->f_highwater = fnp->f_offset; - + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ *err = SUCCESS; return 0; } /* /// BUG!!! Moved to above previous block because we should NOT be able - to truncate the file if we can't write to it. - Ron Cemer + to truncate the file if we can't write to it. - Ron Cemer */ /* test that we have a valid mode for this fnode */ /* if (fnp->f_mode != WRONLY && fnp->f_mode != RDWR) @@ -1686,6 +1776,7 @@ UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err) fnp->f_back = LONG_LAST_CLUSTER; fnp->f_sector = 0; fnp->f_boff = 0; + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ } /* The more difficult scenario is the (more common) */ @@ -1723,19 +1814,22 @@ UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err) return ret_cnt; case SUCCESS: + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ break; } } /* XFR_WRITE case only - if we're at the end, the next */ /* FAT is an EOF marker, so just extend the file length */ - if (last_link(fnp)) + if (last_link(fnp)) { if (!extend(fnp)) { dir_close(fnp); *err = DE_HNDLDSKFULL; return ret_cnt; } + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ + } /* Compute the block within the cluster and the offset */ /* within the block. */ @@ -1809,6 +1903,7 @@ UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err) fnp->f_highwater = fnp->f_offset; fnp->f_dir.dir_size = fnp->f_highwater; } + merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */ } *err = SUCCESS; return ret_cnt; diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index 55b8930..b445cd6 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -36,6 +36,9 @@ BYTE *RcsId = "$Id$"; /* * $Log$ + * Revision 1.10 2000/10/29 23:51:56 jimtabor + * Adding Share Support by Ron Cemer + * * Revision 1.9 2000/08/06 05:50:17 jimtabor * Add new files and update cvs with patches and changes * @@ -1348,6 +1351,21 @@ dispatch: } 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) + r->FLAGS |= FLG_CARRY; + else + r->FLAGS &= ~FLG_CARRY; + r->AX = -rc; + break; +/* /// End of additions for SHARE. - Ron Cemer */ + /* UNDOCUMENTED: server, share.exe and sda function */ case 0x5d: switch (r->AL)