BOOL FcbFindNext(xfcb FAR * lpXfcb) { BYTE FAR *lpOldDta; BYTE FAR *lpDir; COUNT nIdx, 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, PriPathName, &FcbDrive); if ((xfcb FAR *) lpFcb != lpXfcb) { wAttr = lpXfcb->xfcb_attrib; fbcopy(lpXfcb, lpDir, 7); lpDir += 7; } else wAttr = D_ALL; /* Reconstrct the dirmatch structure from the fcb */ *lpDir++ = FcbDrive; Dmatch.dm_drive = FcbDrive ? FcbDrive - 1 : default_drive; fbcopy(lpFcb->fcb_fname, (BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); upMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); Dmatch.dm_attr_srch = wAttr; Dmatch.dm_entry = lpFcb->fcb_diroff; Dmatch.dm_cluster = lpFcb->fcb_dirclst; if (dos_findnext() != SUCCESS) { dta = lpPsp->ps_dta; return FALSE; } MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir); lpFcb->fcb_dirclst = Dmatch.dm_cluster; lpFcb->fcb_diroff = Dmatch.dm_entry; dta = lpPsp->ps_dta; return TRUE; }
/* Enumerate the next file. */ uint gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen) { int code; char *p, *q; if ( pfen->first_time ) { code = dos_findfirst(pfen->pattern, &pfen->ffblk); pfen->first_time = 0; } else code = dos_findnext(&pfen->ffblk); if ( code != 0 ) { /* All done, clean up. */ gp_enumerate_files_close(pfen); return ~(uint)0; } if ( maxlen < 13 + pfen->head_size ) return maxlen + 1; /* cop out! */ memcpy(ptr, pfen->pattern, pfen->head_size); for ( p = &pfen->ffblk.ff_name[0], q = ptr + pfen->head_size; *p; p++ ) if ( *p != ' ' ) *q++ = *p; return q - ptr; }
BOOL FcbDelete(xfcb FAR * lpXfcb) { COUNT FcbDrive; /* Build a traditional DOS file name */ CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); /* check for a device */ /* if we have an extension, can't be a device */ if (IsDevice(PriPathName)) { return FALSE; } else { BYTE FAR *lpOldDta = dta; dmatch Dmatch; dta = (BYTE FAR *) & Dmatch; if (dos_findfirst(D_ALL, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS) { dta = lpOldDta; return FALSE; } do { if (dos_delete(Dmatch.dm_name) != SUCCESS) { dta = lpOldDta; return FALSE; } } while (dos_findnext() == SUCCESS); dta = lpOldDta; return TRUE; } }
COUNT DosFindNext(void) { return dos_findnext(); }
BOOL FcbRename(xfcb FAR * lpXfcb) { rfcb FAR *lpRenameFcb; COUNT FcbDrive; /* Build a traditional DOS file name */ lpRenameFcb = (rfcb FAR *) CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); /* check for a device */ /* if we have an extension, can't be a device */ if (IsDevice(PriPathName)) { return FALSE; } else { BYTE FAR *lpOldDta = dta; dmatch Dmatch; dta = (BYTE FAR *) & Dmatch; if (dos_findfirst(D_ALL, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS) { dta = lpOldDta; return FALSE; } do { fcb LocalFcb; BYTE *pToName, *pszFrom; BYTE FAR *pFromPattern; COUNT nIndex; /* First, expand the find match into fcb style */ /* file name entry */ /* Fill with blanks first */ for (pToName = LocalFcb.fcb_fname, nIndex = 0; nIndex < FNAME_SIZE; nIndex++) { *pToName++ = ' '; } for (pToName = LocalFcb.fcb_fext, nIndex = 0; nIndex < FEXT_SIZE; nIndex++) { *pToName++ = ' '; } /* next move in the file name while overwriting */ /* the filler blanks */ pszFrom = Dmatch.dm_name; pToName = LocalFcb.fcb_fname; for (nIndex = 0; nIndex < FNAME_SIZE; nIndex++) { if (*pszFrom != 0 && *pszFrom != '.') *pToName++ = *pszFrom++; else if (*pszFrom == '.') { ++pszFrom; break; } else break; } if (*pszFrom != '\0') { pToName = LocalFcb.fcb_fext; for (nIndex = 0; nIndex < FEXT_SIZE; nIndex++) { if (*pszFrom != '\0') *pToName++ = *pszFrom++; else break; } } /* Overlay the pattern, skipping '?' */ /* I'm cheating because this assumes that the */ /* struct alignments are on byte boundaries */ pToName = LocalFcb.fcb_fname; for (pFromPattern = lpRenameFcb->renNewName, nIndex = 0; nIndex < FNAME_SIZE + FEXT_SIZE; nIndex++) { if (*pFromPattern != '?') *pToName++ = *pFromPattern++; else ++pFromPattern; } /* now to build a dos name again */ LocalFcb.fcb_drive = 0; FcbNameInit((fcb FAR *) & LocalFcb, PriPathName, &FcbDrive); if (dos_rename(Dmatch.dm_name, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS) { dta = lpOldDta; return FALSE; } } while (dos_findnext() == SUCCESS); dta = lpOldDta; return TRUE; } }
COUNT dos_findfirst(UCOUNT attr, BYTE * name) { REG f_node_ptr fnp; REG dmatch *dmp = &sda_tmp_dm; REG COUNT i; /* printf("ff %Fs\n", name);*/ /* The findfirst/findnext calls are probably the worst of the */ /* DOS calls. They must work somewhat on the fly (i.e. - open */ /* but never close). Since we don't want to lose fnodes every */ /* time a directory is searched, we will initialize the DOS */ /* dirmatch structure and then for every find, we will open the */ /* current directory, do a seek and read, then close the fnode. */ /* Parse out the file name */ i = ParseDosName(name, SearchDir.dir_name, TRUE); if (i < SUCCESS) return i; /* printf("\nff %s", Tname); printf("ff %s", fcbname); */ /* Now search through the directory to find the entry... */ /* 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 (while ignoring LFN entries). */ /* RBIL: ignore ReaDONLY and ARCHIVE bits */ /* For compatibility with bad search requests, only treat as */ /* volume search if only volume bit set, else ignore it. */ if ((attr & ~(D_RDONLY | D_ARCHIVE))==D_VOLID) i = 3; else attr &= ~D_VOLID; /* ignore volume mask */ /* Now open this directory so that we can read the */ /* fnode entry and do a match on it. */ /* printf("dir_open %s\n", szDirName);*/ { char tmp = name[i]; name[i] = '\0'; if ((fnp = dir_open(name)) == NULL) return DE_PATHNOTFND; name[i] = tmp; } /* Now initialize the dirmatch structure. */ dmp->dm_drive = name[0] - 'A'; dmp->dm_attr_srch = attr; /* Copy the raw pattern from our data segment to the DTA. */ fmemcpy(dmp->dm_name_pat, SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); if ((attr & D_VOLID)==D_VOLID) /* search for VOL label ignore RDONLY & ARCHIVE */ { /* Now do the search */ while (dir_read(fnp) == 1) { /* Test the attribute and return first found */ if ((fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE)) == D_VOLID && fnp->f_dir.dir_name[0] != DELETED) { dmp->dm_dircluster = fnp->f_dirstart; /* TE */ memcpy(&SearchDir, &fnp->f_dir, sizeof(struct dirent)); FDirDbgPrintf(("dos_findfirst: %11s\n", fnp->f_dir.dir_name)); dir_close(fnp); return SUCCESS; } fnp->f_diroff++; } /* Now that we've done our failed search, close it and */ /* return an error. */ dir_close(fnp); return DE_NFILES; } /* Otherwise just do a normal find next */ else { dmp->dm_entry = 0; dmp->dm_dircluster = fnp->f_dirstart; dir_close(fnp); return dos_findnext(); } }
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);*/ /* The findfirst/findnext calls are probably the worst of the */ /* DOS calls. They must work somewhat on the fly (i.e. - open */ /* but never close). Since we don't want to lose fnodes every */ /* time a directory is searched, we will initialize the DOS */ /* dirmatch structure and then for every find, we will open the */ /* 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) return i; /* printf("\nff %s", Tname); printf("ff %s", local_name); printf("ff %s\n", local_ext); */ /* 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'; } /* 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; /* Now initialize the dirmatch structure. */ nDrive=get_verify_drive(name); if (nDrive < 0) return nDrive; dmp->dm_drive = nDrive; dmp->dm_attr_srch = attr; /* Copy the raw pattern from our data segment to the DTA. */ fmemcpy(dmp->dm_name_pat, SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); if (attr == D_VOLID) { /* Now do the search */ while (dir_read(fnp) == 1) { /* Test the attribute and return first found */ if ((fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE)) == D_VOLID) { dmp->dm_dircluster = fnp->f_dirstart; /* TE */ memcpy(&SearchDir, &fnp->f_dir, sizeof(struct dirent)); dir_close(fnp); return SUCCESS; } } /* Now that we've done our failed search, close it and */ /* return an error. */ dir_close(fnp); return DE_FILENOTFND; } /* Otherwise just do a normal find next */ else { dmp->dm_entry = 0; if (!fnp->f_flags.f_droot) dmp->dm_dircluster = fnp->f_dirstart; else dmp->dm_dircluster = 0; dir_close(fnp); return dos_findnext(); } }
COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name) { REG struct f_node FAR *fnp; REG dmatch FAR *dmp = (dmatch FAR *) dta; REG COUNT i; COUNT nDrive; BYTE *p; struct cds FAR *cdsp; static BYTE local_name[FNAME_SIZE + 1], local_ext[FEXT_SIZE + 1]; /* The findfirst/findnext calls are probably the worst of the */ /* DOS calls. They must work somewhat on the fly (i.e. - open */ /* but never close). Since we don't want to lose fnodes every */ /* time a directory is searched, we will initialize the DOS */ /* dirmatch structure and then for every find, we will open the */ /* current directory, do a seek and read, then close the fnode. */ /* Start out by initializing the dirmatch structure. */ dmp->dm_drive = default_drive; dmp->dm_entry = 0; dmp->dm_cluster = 0; dmp->dm_attr_srch = attr | D_RDONLY | D_ARCHIVE; /* Parse out the drive, file name and file extension. */ i = ParseDosName(name, &nDrive, &LocalPath[2], local_name, local_ext, TRUE); if (i != SUCCESS) return i; if (nDrive >= 0) { dmp->dm_drive = nDrive; } else nDrive = default_drive; cdsp = &CDSp->cds_table[nDrive]; if (cdsp->cdsFlags & 0x8000) { if (Remote_find(REM_FINDFIRST, attr, name, dmp) != 0) return DE_FILENOTFND; return SUCCESS; } /* Now build a directory. */ if (!LocalPath[2]) strcpy(&LocalPath[2], "."); /* 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 != '*'; ++p, ++i) SearchDir.dir_name[i] = *p; if (*p == '*') { for (; i < FNAME_SIZE; ++i) SearchDir.dir_name[i] = '?'; while (*++p) ; } else 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 != '*'; ++p, ++i) SearchDir.dir_ext[i] = *p; if (*p == '*') { for (; i < FEXT_SIZE; ++i) SearchDir.dir_ext[i] = '?'; while (*++p) ; } else for (; i < FEXT_SIZE; i++) SearchDir.dir_ext[i] = ' '; /* Convert everything to uppercase. */ upMem(SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); /* Copy the raw pattern from our data segment to the DTA. */ fbcopy((BYTE FAR *) SearchDir.dir_name, dmp->dm_name_pat, FNAME_SIZE + FEXT_SIZE); /* Now search through the directory to find the entry... */ /* 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_RDONLY | D_ARCHIVE)) == D_VOLID) { /* Now open this directory so that we can read the */ /* fnode entry and do a match on it. */ if ((fnp = dir_open((BYTE FAR *) "\\")) == NULL) return DE_PATHNOTFND; /* Now do the search */ while (dir_read(fnp) == DIRENT_SIZE) { /* Test the attribute and return first found */ if ((fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE)) == D_VOLID) { pop_dmp(dmp, fnp); dir_close(fnp); return SUCCESS; } } /* Now that we've done our failed search, close it and */ /* return an error. */ dir_close(fnp); return DE_FILENOTFND; } /* Otherwise just do a normal find next */ else { /* Complete building the directory from the passed in */ /* name */ if (nDrive >= 0) LocalPath[0] = 'A' + nDrive; else LocalPath[0] = 'A' + default_drive; LocalPath[1] = ':'; /* Now open this directory so that we can read the */ /* fnode entry and do a match on it. */ if ((fnp = dir_open((BYTE FAR *) LocalPath)) == NULL) return DE_PATHNOTFND; pop_dmp(dmp, fnp); dmp->dm_entry = 0; if (!fnp->f_flags.f_droot) { dmp->dm_cluster = fnp->f_dirstart; dmp->dm_dirstart = fnp->f_dirstart; } else { dmp->dm_cluster = 0; dmp->dm_dirstart = 0; } dir_close(fnp); return dos_findnext(); } }