⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsys.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 5 页
字号:
	*/

	erc = GetClstrValue(Clstr, Drive, 0, &NextClstr, &i);
	if (erc)
		return(erc);
	erc = SetClstrValue(Clstr, 0xFFFF, Drive, &i);  /* new end of chain */
	if (erc)
		return(erc);

	while ((NextClstr) && (NextClstr < MaxClstr)) {
		CrntClstr = NextClstr;
		erc = GetClstrValue(CrntClstr, Drive, 0, &NextClstr, &i);
		if (erc)
			return(erc);
		erc = SetClstrValue(CrntClstr, 0, Drive, &i);  /* Free it up */
		if (erc)
			return(erc);
	}

	/* DONE! */
	return(0);
}

/********************************************************
  This finds the absolute cluster you want from the
  LFA in a particular file. The file handle must already
  be validated!  It also returns the relative LFA of
  the beginning of this cluster.
*********************************************************/

U32 GetAbsoluteClstr(U32 dHandle, U32 dLFA, U16 *pClstrRet, U32 *prLFARet)
{
U32 erc, iFCB, spc, bpc, rLFA;
U16 rClstrWant, rClstrNow, Clstr, MaxClstr;
U8 Drive;

  iFCB = paFUB[dHandle]->iFCB;
  Drive = paFCB[iFCB]->Ldrv;		/* What logical drive are we on? */
  spc = Ldrv[Drive].SecPerClstr;	/* sectors per cluster */
  bpc = spc * 512;					/* bytes per cluster */

 if (Ldrv[Drive].fFAT16)
 	MaxClstr = 0xfff8;
 else
 	MaxClstr = 0xff8;	/* FAT12 */

/*
  Calculate relative by dividing cluster size in bytes by dLFA.
  If zero, we want the 1st cluster which is listed in the FCB.
  If it is greater than zero, we have to "walk the FAT cluster
  chain" until we reach the one we want, then read it in.

  The FUB fields LFAClstr and Clstr store the file LFA of the last
  cluster in this file that was read or written.  This means if the
  LFA is higher than the last read or written, we don't waste the
  time reading the whole chain. We start from where we are.

  The major difference is we may not be reading the first sector
  in the cluster. We figure this out from the dLFA as compared to
  LFAClstr.

*/

  rClstrWant = dLFA / bpc;  					/* Relative clstr they want */
  rClstrNow = paFUB[dHandle]->LFAClstr / bpc;	/* Rel 'Clstr' in FUB */

  if (rClstrWant < rClstrNow)	{			/* Is it earlier in the file? */
	Clstr = paFCB[iFCB]->StartClstr;		/* Yes, start at the beginning */
	rClstrNow = 0;
	rLFA = 0;
	}
  else {
	Clstr = paFUB[dHandle]->Clstr;			/* No, start at current cluster */
	rLFA = paFUB[dHandle]->LFAClstr;		/* LFA of this cluster */
  }

  /* We need to run the cluster chain if rClstrNow < ClstrWant */

  while ((rClstrNow < rClstrWant) &&	/* haven't reach it yet */
         (Clstr < MaxClstr) &&			/* Not last cluster */
         (Clstr))  {					/* A valid cluster */
	  erc = NextFATClstr(Drive, Clstr, &Clstr);
	  if (erc)
	  	return(erc);
	  ++rClstrNow;
	  rLFA += bpc;
  }

  if (rClstrNow != rClstrWant)			/* Cluster chain appears broken... */
    return ErcBrokenFile;

  *pClstrRet = Clstr;
  *prLFARet = rLFA;
  return(0);
}


/*******************************************************
  SetFileSize sets the FileSize entry in the FCB for
  the handle specified.  This means we will allocate
  or deallocate clusters as necessary to satisfy this
  request. The file MUST be open in MODE MODIFY.
  This must be done before a file can be written
  to beyond current FileSize (Block and Stream types).
********************************************************/

U32 SetFileSizeM(U32 dHandle, U32 dSize)
{
U32 erc, i, iFCB, rLFA;
U32 CrntSize, nCrntClstrs, spc, bpc, nClstrsWant;
U16 Clstr;
U8 Drive;

  erc = ValidateHandle(dHandle, &iFCB);
  if (erc)
  	return erc;
  if (!paFCB[iFCB]->Mode)
  	return ErcReadOnly;

  Drive = paFCB[iFCB]->Ldrv;		/* What logical drive are we on? */
  spc = Ldrv[Drive].SecPerClstr;	/* sectors per cluster */
  bpc = spc * 512;					/* bytes per cluster */

  /* Looks like it's valid to change the size */

  CrntSize = paFCB[iFCB]->FileSize;

  if (CrntSize == dSize)		/* No need to do anything! */
  	return(0);

  nCrntClstrs = CrntSize/bpc; 	/* nClusters currently  */
  if (CrntSize%bpc)
  	nCrntClstrs++;

  if (!CrntSize)
  	nCrntClstrs = 1;			/* ZERO length files have 1 Clstr! */

  nClstrsWant = dSize/bpc;  	/* nClusters they we need  */
  if (dSize%bpc)
  	nClstrsWant++;

  if (!dSize)
  	nClstrsWant = 1;			/* ZERO length files have 1 Clstr! */


  if (nClstrsWant == nCrntClstrs)
	erc = 0;

  else if (nClstrsWant > nCrntClstrs) {	/* Need to extend allocation */

	/* get the last cluster in the file */
	erc = GetAbsoluteClstr(dHandle, CrntSize, &Clstr, &rLFA);
	i = nCrntClstrs;
	while ((!erc) && (i < nClstrsWant))  {
			erc = ExtendClstrChain(Drive, Clstr, &Clstr);
			i++;
	}
  }
  else if (nClstrsWant < nCrntClstrs) { /* Need to truncate it */

	/* Get to cluster where it should be truncated */

	erc = GetAbsoluteClstr(dHandle, dSize, &Clstr, &rLFA);
	if (!erc)
		erc = TruncClstrChain(Drive, Clstr);
	/* Now we must ensure that the cluster helper is NOT
	beyond EOF!
	*/
    if (paFUB->LFAClstr > dSize) {
        paFUB->LFAClstr = 0;
        paFUB[dHandle]->Clstr = paFCB[iFCB]->StartClstr;
	}

  }
  if (!erc) {
	paFCB[iFCB]->FileSize = dSize;
	paFCB[iFCB]->fMod = 1;
  }

  return erc;
}



/*******************************************************************
 This searches a directory beginning at Clstr for pName and returns
 a pointer to the 32 byte dir entry which is in a temporary buffer.
 If not found, returns NIL. When searching directories, if the
 filename begins with a NULL the search need go no futher!
********************************************************************/

U32 GetDirEnt(U8  *pName,
              U8  Drive,
              U16 Clstr,
              U32 *pLBARet,
              U32 *poEntRet,
              U8  **pEntRet)
{
unsigned long sector, i, j, k, erc;
U8 fFound, fEnd, *pEnt, *pStart;
U16 MaxClstr;

 j = Ldrv[Drive].SecPerClstr;		/* How many sectors per cluster */
 sector = ClsToLBA(Clstr, Drive);	/* absolute sector of first dir sector */
 if (Ldrv[Drive].fFAT16)
 	MaxClstr = 0xfff8;
 else
 	MaxClstr = 0xff8;	/* FAT12 */
 i = 0;
 fEnd=0;
 fFound=0;

  fFound= 0;
  while ((!fFound) && (!fEnd)) {		/* while there are valid entries */
	if (i==j) {		/* reached last dir sector of this cluster */
		erc = NextFATClstr(Drive, Clstr, &Clstr);
		if (!erc) {
			if (Clstr >= MaxClstr)				/* last sector */
				return(ErcNoSuchFile);			/* not found */
			sector = ClsToLBA(Clstr, Drive);	/* LBA of next dir sector */
			i=0;
		}
		else {
			*pEntRet = 0;
			return(erc);
		}
	}

	erc = DeviceOp(Ldrv[Drive].DevNum, 1, sector++, 1, abDirSectBuf);
	if (erc)
		return(erc);

	++i;		/* next sector in cluster */

    pEnt = &abDirSectBuf[0];
    pStart = pEnt;

	for (k=0; k<16; k++) {		/* 16 entries per sector */
		if (*pEnt==0) {			/* 0 in a DirEnt stops search */
			fEnd=1;
			break;
			}

		if (CompareNCS(pEnt, pName, 11) == -1) {
			fFound=1;
            *pLBARet = sector-1;		/* tell em what LBA of DirEnt */
            *poEntRet = pEnt-pStart;	/* Tell em offset in LBA */
			break;
			}
		pEnt+=32;	/* 32 byte per entry */
		}
	}
  if (fFound) {
  	*pEntRet = pEnt;
  	return(0);
  }
  else return (ErcNoSuchFile);
}


/*****************************************************
 This searches the ROOT directory for pName
 and returns a pointer to the 32 byte entry which
 is in a temporary buffer. If not found, returns NIL;
 When searching directories, if the filename begins
 with a NULL the search need go no futher!
*****************************************************/

U32 GetRootEnt(U8  *pName,
               U8  Drive,
               U32 *pLBARet,
               U32 *poEntRet,
               U8  **pEntRet)
{
unsigned long i, j, k, erc;
U8 fFound, fEnd, *pEnt, *pStart;

 i = Ldrv[Drive].LBARoot;
 j = Ldrv[Drive].nRootDirEnt;

 fFound = 0;
 fEnd = 0;
 while ((j) && (!fFound) && (!fEnd)) {	/* while there are valid entries */

	erc = DeviceOp(Ldrv[Drive].DevNum, 1, i++, 1, abRawSector);

	if (erc)
		return(erc);

    pEnt = abRawSector;
    pStart = pEnt;
	for (k=0; k<16; k++) {
		if (*pEnt==0) {			/* 0 in a DirEnt stops search */
			fEnd=1;
			break;
		}
		if (CompareNCS(pEnt, pName, 11) == -1) {
			fFound=1;
            *pLBARet = i-1;				 /* tell em what LBA of DirEnt */
            *poEntRet = pEnt-pStart;	 /* Tell em offset in LBA */
			break;
		}
		--j;		/* one less dir ent */
		pEnt+=32;	/* 32 byte per entry */
	}
 }
 if (fFound) {
 	*pEntRet = pEnt;
 	return(0);
 }
 else
	return (ErcNoSuchFile);
}

/********************************************
  This builds a full file specification from
  pName and places it in pDest based on the
  path from iJob. cbDestRet is set to size.
*********************************************/

void BuildSpec(char *pName,
			   long cbName,
			   char *pDest,
			   long *cbDestRet,
			   long iJob)
{
long i;

 if ((cbName) && (pName) && (pName[1] == ':')) {		/* Do NOT use path */
	 CopyData(pName, pDest, cbName);
	 i = cbName;
 }
 else {										/* Use path as prefix */
	i = 0;
	GetPath(iJob, pDest, &i);
	if ((cbName) && (pName)) {
		CopyData(pName, &pDest[i], cbName);
		i += cbName;
	}
 }
 *cbDestRet = i;
}



/*****************************************************
 The parses out the path name into directories, filename,
 and extension  (Example):
 C:\TEMP\TEST.TXT  (with TEMP being a dir in the root).
 This also uses the current path for the job to build
 the filename.  If the name starts with \ or "DRIVE:"
 then the path from the JCB is NOT used. Otherwise
 the pName is cancatenated to the job's path.
 SpecDepth is set to the level of the last valid
 11 character string (0-6).
*****************************************************/

U32 ParseName(U8 *pName, U32 cbName, U32 iJob)
{
unsigned long i, j, k, erc;
U8 c, *pPart;
char Spec[70];
U32 cbSpec;

 erc = 0;
 FDrive = 0;

 FillData(FileSpec, (7*11), ' '); 		/* Fill parse table with spaces */

 BuildSpec(pName, cbName, Spec, &cbSpec, iJob);

 j = 0;		/* index into crnt part of spec */
 k = 0;		/* index into crnt tree level   */
 pPart = Spec;
 for (i=0; i < cbSpec; i++) {
	switch (c = *pPart++) {
		case 0x5c  : 	/* '\' separates dir or fname */
			if (j>0) {  /* if it's not the first one */
				++k;
				j=0;
			}
			break;
		case ':' :
			if ((j==1) && (k==0) && (FDrive==0)) {
				FDrive = FileSpec[0][0] & 0xdf;  /* Make drive Upper*/
                FileSpec[0][0] = ' ';
				j=0;			/* back to beginning of part */
				k=0;
			}
			else erc = ErcBadFileSpec;
			break;
		case '.'  :  			/* . can only appear once in dir or fname */
			if (j>8) erc = ErcBadFileSpec;
			else j=8;						/* move to extension */
			break;
		case '>'  :							/* not allowed in spec */
		case '<'  :
		case ','  :
		case '+'  :
		case '|'  :
		case ']'  :
		case '['  :
		case '+'  :
		case '='  :
		case '@'  :
		case '*'  :
		case '?'  :
			 erc = ErcBadFileSpec;
			break;
		default   :							/* make chars upper */
			if (j>10)
				erc = ErcBadFileSpec;
			else {
				if (((c >= 'A') && (c <= 'Z')) ||
				    ((c >= 'a') && (c <= 'z')))
					   c &= 0xdf;
	            FileSpec[k][j] = c;
	            ++j;
	            }
			break;
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -