📄 dosfns.c
字号:
(strlen(PriPathName) >= sizeof(current_ldt->cdsCurrentPath))) return DE_PATHNOTFND;#if defined(CHDIR_DEBUG) printf("Remote Chdir: n='%Fs' p='%Fs\n", s, PriPathName);#endif /* now get fs to change to new */ /* directory */ result = (result & IS_NETWORK ? network_redirector(REM_CHDIR) : dos_cd(PriPathName));#if defined(CHDIR_DEBUG) printf("status = %04x, new_path='%Fs'\n", result, cdsd->cdsCurrentPath);#endif if (result != SUCCESS) return result;/* Copy the path to the current directory structure. Some redirectors do not write back to the CDS. SHSUCdX needs this. jt*/ fstrcpy(current_ldt->cdsCurrentPath, PriPathName); if (FP_OFF(current_ldt) != 0xFFFF) { fstrcpy(current_ldt->cdsCurrentPath, PriPathName); if (PriPathName[7] == 0) current_ldt->cdsCurrentPath[8] = 0; /* Need two Zeros at the end */ } return SUCCESS;}STATIC VOID pop_dmp(dmatch FAR * dmp){ dmp->dm_attr_fnd = (BYTE) SearchDir.dir_attrib; dmp->dm_time = SearchDir.dir_time; dmp->dm_date = SearchDir.dir_date; dmp->dm_size = (LONG) SearchDir.dir_size; ConvertName83ToNameSZ(dmp->dm_name, (BYTE FAR *) SearchDir.dir_name);}COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name){ int rc; register dmatch FAR *dmp = dta; rc = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH | CDS_MODE_ALLOW_WILDCARDS); if (rc < SUCCESS) return rc; /* /// Added code here to do matching against device names. DOS findfirst will match exact device names if the filename portion (excluding the extension) contains a valid device name. Credits: some of this code was ripped off from truename() in newstuff.c. - Ron Cemer */ SAttr = (BYTE) attr;#if defined(FIND_DEBUG) printf("Remote Find: n='%Fs\n", PriPathName);#endif dta = &sda_tmp_dm; memset(&sda_tmp_dm, 0, sizeof(dmatch)+sizeof(struct dirent)); if (rc & IS_NETWORK) rc = network_redirector_fp(REM_FINDFIRST, current_ldt); else if (rc & IS_DEVICE) { const char *p; 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 = (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++; rc = SUCCESS; /* /// End of additions. - Ron Cemer ; heavily edited - Bart Oldeman */ } else rc = dos_findfirst(attr, PriPathName); dta = dmp; if (rc == SUCCESS) { fmemcpy(dta, &sda_tmp_dm, 21); pop_dmp(dmp); } return rc;}COUNT DosFindNext(void){ COUNT rc; register dmatch FAR *dmp = dta; /* findnext will always fail on a device name device name or volume id */ if (dmp->dm_attr_fnd & (D_DEVICE | D_VOLID)) return DE_NFILES;/* * The new version of SHSUCDX 1.0 looks at the dm_drive byte to * test 40h. I used RamView to see location MSD 116:04be and * FD f??:04be, the byte set with 0xc4 = Remote/Network drive 4. * Ralf Brown docs for dos 4eh say bit 7 set == remote so what is * bit 6 for? * SHSUCDX Mod info say "test redir not network bit". * Just to confuse the rest, MSCDEX sets bit 5 too. * * So, assume bit 6 is redirector and bit 7 is network. * jt * Bart: dm_drive can be the drive _letter_. * but better just stay independent of it: we only use * bit 7 to detect a network drive; the rest untouched. * RBIL says that findnext can only return one error type anyway * (12h, DE_NFILES) */#if 0 printf("findnext: %d\n", dmp->dm_drive);#endif fmemcpy(&sda_tmp_dm, dmp, 21); memset(&SearchDir, 0, sizeof(struct dirent)); dta = &sda_tmp_dm; rc = (sda_tmp_dm.dm_drive & 0x80) ? network_redirector_fp(REM_FINDNEXT, &sda_tmp_dm) : dos_findnext(); dta = dmp; if (rc == SUCCESS) { fmemcpy(dmp, &sda_tmp_dm, 21); pop_dmp(dmp); } return rc;}COUNT DosGetFtime(COUNT hndl, date * dp, time * tp){ sft FAR *s;/*sfttbl FAR *sp;*/ /* Get the SFT block that contains the SFT */ if (FP_OFF(s = get_sft(hndl)) == (size_t) - 1) return DE_INVLDHNDL; /* If SFT entry refers to a device, return the date and time of opening */ if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED)) { *dp = s->sft_date; *tp = s->sft_time; return SUCCESS; } /* call file system handler */ return dos_getftime(s->sft_status, dp, tp);}COUNT DosSetFtimeSft(int sft_idx, date dp, time tp){ /* Get the SFT block that contains the SFT */ sft FAR *s = idx_to_sft(sft_idx); if (FP_OFF(s) == (size_t) - 1) return DE_INVLDHNDL; /* If SFT entry refers to a device, do nothing */ if (s->sft_flags & SFT_FDEVICE) return SUCCESS; s->sft_flags |= SFT_FDATE; s->sft_date = dp; s->sft_time = tp; if (s->sft_flags & SFT_FSHARED) return SUCCESS; /* call file system handler */ return dos_setftime(s->sft_status, dp, tp);}COUNT DosGetFattr(BYTE FAR * name){ COUNT result; 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 */ /* 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*/ if (PriPathName[3] == '\0') return 0x10; if (result & IS_NETWORK) return network_redirector(REM_GETATTRZ); 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. The reason for using truename()'s result is that dos_?etfattr() are very low-level functions and don't handle full path expansion or cleanup, such as converting "c:\a\b\.\c\.." to "C:\A\B". - Ron Cemer*//* memcpy(SecPathName,PriPathName,sizeof(SecPathName)); return dos_getfattr(SecPathName, attrp);*/ /* no longer true. dos_getfattr() is A) intelligent (uses dos_open) anyway B) there are some problems with MAX_PARSE, i.e. if PATH ~= 64 and TRUENAME adds a C:, which leeds to trouble. the problem was discovered, when VC did something like fd = DosOpen(filename,...) jc can't_copy_dialog; attr = DosGetAttrib(filename); jc can't_copy_dialog; and suddenly, the filehandle stays open shit. tom */ 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; result = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH); if (result < SUCCESS) return result; if (result & IS_NETWORK) return remote_setfattr(attrp); 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. - Ron Cemer*//* memcpy(SecPathName,PriPathName,sizeof(SecPathName)); return dos_setfattr(SecPathName, attrp); see DosGetAttr()*/ return dos_setfattr(PriPathName, attrp);}UBYTE DosSelectDrv(UBYTE drv){ current_ldt = get_cds(drv); if (current_ldt != NULL) default_drive = drv; return lastdrive;}COUNT DosDelete(BYTE FAR * path, int attrib){ COUNT result; result = truename(path, PriPathName, CDS_MODE_CHECK_DEV_PATH); if (result < SUCCESS) return result; if (result & IS_NETWORK) return network_redirector(REM_DELETE); if (result & IS_DEVICE) return DE_FILENOTFND; return dos_delete(PriPathName, attrib);}COUNT DosRenameTrue(BYTE * path1, BYTE * path2, int attrib){ if (path1[0] != path2[0]) { return DE_DEVICE; /* not same device */ } if (FP_OFF(current_ldt) == 0xFFFF || (current_ldt->cdsFlags & CDSNETWDRV)) return network_redirector(REM_RENAME); return dos_rename(path1, path2, attrib);}COUNT DosRename(BYTE FAR * path1, BYTE FAR * path2){ COUNT result; result = truename(path2, SecPathName, CDS_MODE_CHECK_DEV_PATH); if (result < SUCCESS) return result; if ((result & (IS_NETWORK | IS_DEVICE)) == IS_DEVICE) return DE_FILENOTFND; result = truename(path1, PriPathName, CDS_MODE_CHECK_DEV_PATH); if (result < SUCCESS) return result; if ((result & (IS_NETWORK | IS_DEVICE)) == IS_DEVICE) return DE_FILENOTFND; return DosRenameTrue(PriPathName, SecPathName, D_ALL);}COUNT DosMkRmdir(const char FAR * dir, int action){ COUNT result; result = truename(dir, PriPathName, CDS_MODE_CHECK_DEV_PATH); if (result < SUCCESS) return result; if (result & IS_NETWORK) return network_redirector(action == 0x39 ? REM_MKDIR : REM_RMDIR); if (result & IS_DEVICE) return DE_ACCESS; return (action == 0x39 ? dos_mkdir : dos_rmdir)(PriPathName);}/* /// Added for SHARE. - Ron Cemer */COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock){ sft FAR *s; /* Get the SFT block that contains the SFT */ if (FP_OFF(s = get_sft(hndl)) == (size_t) - 1) return DE_INVLDHNDL; if (s->sft_flags & SFT_FSHARED) return remote_lock_unlock(s, pos, len, unlock); /* Invalid function unless SHARE is installed or remote. */ if (!IsShareInstalled()) return DE_INVLDFUNC; /* 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. *//* check for a device returns device header if match, else returns NULL can only match character devices (as only they have names) */struct dhdr FAR *IsDevice(const char FAR * fname){ struct dhdr FAR *dhp; const char FAR *froot = get_root(fname); int i;/* /// BUG!!! This is absolutely wrong. A filename of "NUL.LST" must be treated EXACTLY the same as a filename of "NUL". The existence or content of the extension is irrelevent in determining whether a filename refers to a device. - Ron Cemer // if we have an extension, can't be a device <--- WRONG. if (*froot != '.') {*//* BUGFIX: MSCD000<00> should be handled like MSCD000<20> TE ie the 8 character device name may be padded with spaces ' ' or NULs '\0' Note: fname is assumed an ASCIIZ string (ie not padded, unknown length) but the name in the device header is assumed FNAME_SIZE and padded. KJD*/ /* check for names that will never be devices to avoid checking all device headers. only the file name (not path nor extension) need be checked, "" == root or empty name */ if ( (*froot == '\0') || ((*froot=='.') && ((*(froot+1)=='\0') || (*(froot+2)=='\0' && *(froot+1)=='.'))) ) { return NULL; } /* cycle through all device headers checking for match */ for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) { if (!(dhp->dh_attr & ATTR_CHAR)) /* if this is block device, skip */ continue; for (i = 0; i < FNAME_SIZE; i++) { unsigned char c1 = (unsigned char)froot[i]; /* ignore extensions and handle filenames shorter than FNAME_SIZE */ if (c1 == '.' || c1 == '\0') { /* check if remainder of device name consists of spaces or nulls */ for (; i < FNAME_SIZE; i++) { unsigned char c2 = dhp->dh_name[i]; if (c2 != ' ' && c2 != '\0') break; } break; } if (DosUpFChar(c1) != DosUpFChar(dhp->dh_name[i])) break; } /* if found a match then return device header */ if (i == FNAME_SIZE) return dhp; } return NULL;}/* /// Added for SHARE. - Ron Cemer */BOOL IsShareInstalled(void){ extern unsigned char ASMPASCAL share_check(void); if (!share_installed && share_check() == 0xff) share_installed = TRUE; return share_installed;}/* /// End of additions for SHARE. - Ron Cemer */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, CDS_MODE_ALLOW_WILDCARDS); if (rc >= SUCCESS) fstrcpy(dest, PriPathName); return rc;}STATIC int remote_lock_unlock(sft FAR *sftp, /* SFT for file */ unsigned long ofs, /* offset into file */ unsigned long len, /* length (in bytes) of region to lock or unlock */ int unlock) /* one to unlock; zero to lock */{ struct { unsigned long ofs, len; int unlock; } param_block; param_block.ofs = ofs; param_block.len = len; param_block.unlock = unlock; return (int)network_redirector_mx(REM_LOCK, sftp, ¶m_block);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -