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

📄 dir.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Bare format */
		DirPrintBareList(ptrFiles, dwCount, szCurPath, lpFlags);
	}
	else if(lpFlags->bShortName)
	{
		/* New list style / Short names */
		DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
	}
	else if(lpFlags->bWideListColSort || lpFlags->bWideList)
	{
		/* Wide list */
		DirPrintWideList(ptrFiles, dwCount, szCurPath, lpFlags);
	}
	else if (lpFlags->bNewLongList )
	{
		/* New list style*/
		DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
	}
	else
	{
		/* If nothing is selected old list is the default */
		DirPrintOldList(ptrFiles, dwCount, szCurPath, lpFlags);
	}
}



/*
 * CompareFiles
 *
 * Compares 2 files based on the order criteria
 */
static BOOL
CompareFiles(LPWIN32_FIND_DATA lpFile1,	/* [IN] A pointer to WIN32_FIND_DATA of file 1 */
			 LPWIN32_FIND_DATA lpFile2,	/* [IN] A pointer to WIN32_FIND_DATA of file 2 */
			 LPDIRSWITCHFLAGS lpFlags)	/* [IN] The flags that we use to list */
{
  ULARGE_INTEGER u64File1;
  ULARGE_INTEGER u64File2;
  int i;
  long iComp = 0;					/* The comparison result */

	/* Calculate critiries by order given from user */
	for (i = 0;i < lpFlags->stOrderBy.sCriteriaCount;i++)
	{

		/* Calculate criteria */
		switch(lpFlags->stOrderBy.eCriteria[i])
		{
		case ORDER_SIZE:		/* Order by size /o:s */
			/* concat the 32bit integers to a 64bit */
			u64File1.LowPart = lpFile1->nFileSizeLow;
			u64File1.HighPart = lpFile1->nFileSizeHigh;
			u64File2.LowPart = lpFile2->nFileSizeLow;
			u64File2.HighPart = lpFile2->nFileSizeHigh;

			/* In case that differnce is too big for a long */
			if (u64File1.QuadPart < u64File2.QuadPart)
				iComp = -1;
			else if (u64File1.QuadPart > u64File2.QuadPart)
				iComp = 1;
			else
				iComp = 0;
			break;

		case ORDER_DIRECTORY:	/* Order by directory attribute /o:g */
			iComp = ((lpFile2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)-
				(lpFile1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
			break;

		case ORDER_EXTENSION:	/* Order by extension name /o:e */
			iComp = _tcsicmp(getExt(lpFile1->cFileName),getExt(lpFile2->cFileName));
			break;

		case ORDER_NAME:		/* Order by filename /o:n */
			iComp = _tcsicmp(lpFile1->cFileName, lpFile2->cFileName);
			break;

		case ORDER_TIME:		/* Order by file's time /o:t */
			/* We compare files based on the time field selected by /t */
			switch(lpFlags->stTimeField.eTimeField)
			{
			case TF_CREATIONDATE:
				/* concat the 32bit integers to a 64bit */
				u64File1.LowPart = lpFile1->ftCreationTime.dwLowDateTime;
				u64File1.HighPart = lpFile1->ftCreationTime.dwHighDateTime ;
				u64File2.LowPart = lpFile2->ftCreationTime.dwLowDateTime;
				u64File2.HighPart = lpFile2->ftCreationTime.dwHighDateTime ;
				break;
			case TF_LASTACCESSEDDATE :
				/* concat the 32bit integers to a 64bit */
				u64File1.LowPart = lpFile1->ftLastAccessTime.dwLowDateTime;
				u64File1.HighPart = lpFile1->ftLastAccessTime.dwHighDateTime ;
				u64File2.LowPart = lpFile2->ftLastAccessTime.dwLowDateTime;
				u64File2.HighPart = lpFile2->ftLastAccessTime.dwHighDateTime ;
				break;
			case TF_MODIFIEDDATE:
				/* concat the 32bit integers to a 64bit */
				u64File1.LowPart = lpFile1->ftLastWriteTime.dwLowDateTime;
				u64File1.HighPart = lpFile1->ftLastWriteTime.dwHighDateTime ;
				u64File2.LowPart = lpFile2->ftLastWriteTime.dwLowDateTime;
				u64File2.HighPart = lpFile2->ftLastWriteTime.dwHighDateTime ;
				break;
			}

			/* In case that differnce is too big for a long */
			if (u64File1.QuadPart < u64File2.QuadPart)
				iComp = -1;
			else if (u64File1.QuadPart > u64File2.QuadPart)
				iComp = 1;
			else
				iComp = 0;
			break;
		}

		/* Reverse if desired */
		if (lpFlags->stOrderBy.bCriteriaRev[i])
			iComp *= -1;

		/* If that criteria was enough for distinguishing
		   the files/dirs,there is no need to calculate the others*/
		if (iComp != 0) break;
	}

	/* Translate the value of iComp to boolean */
	if (iComp > 0)
		return TRUE;
	else
		return FALSE;
}

/*
 * QsortFiles
 *
 * Sort files by the order criterias using quicksort method
 */
static VOID
QsortFiles(LPWIN32_FIND_DATA ptrArray[],	/* [IN/OUT] The array with file info pointers */
	   int i,				/* [IN]     The index of first item in array */
	   int j,				/* [IN]     The index to last item in array */
	   LPDIRSWITCHFLAGS lpFlags)		/* [IN]     The flags that we will use to sort */
{
	LPWIN32_FIND_DATA lpTemp;	/* A temporary pointer */
	int First, Last, Temp;
	BOOL Way;

	if (i < j)
	{
		First = i;
		Last = j;
		Way = TRUE;
		while (i != j)
		{
			if (Way == CompareFiles(ptrArray[i], ptrArray[j], lpFlags))
			{
				/* Swap the pointers of the array */
				lpTemp = ptrArray[i];
				ptrArray[i]= ptrArray[j];
				ptrArray[j] = lpTemp;

				/* Swap the indexes for inverting sorting */
				Temp = i;
				i = j;
				j =Temp;

				Way = !Way;
			}

			j += (!Way - Way);
		}

		QsortFiles(ptrArray,First, i-1, lpFlags);
		QsortFiles(ptrArray,i+1,Last, lpFlags);
	}
}



/*
 * DirList
 *
 * The functions that does everything except for printing results
 */
static INT
DirList(LPTSTR szPath,			/* [IN] The path that dir starts */
		LPTSTR szFilespec,		/* [IN] The type of file that we are looking for */
		LPINT pLine,			/* FIXME: Maybe used for paginating */
		LPDIRSWITCHFLAGS lpFlags)	/* [IN] The flags of the listing */
{
	HANDLE hSearch;							/* The handle of the search */
	HANDLE hRecSearch;						/* The handle for searching recursivly */
	WIN32_FIND_DATA wfdFileInfo;			/* The info of file that found */
	LPWIN32_FIND_DATA * ptrFileArray;		/* An array of pointers with all the files */
	PDIRFINDLISTNODE ptrStartNode;	/* The pointer to the first node */
	PDIRFINDLISTNODE ptrNextNode;	/* A pointer used for relatives refernces */
TCHAR szFullPath[MAX_PATH];				/* The full path that we are listing with trailing \ */
TCHAR szFullFileSpec[MAX_PATH];			/* The full path with file specs that we ll request\ */
DWORD dwCount;							/* A counter of files found in directory */
DWORD dwCountFiles;						/* Counter for files */
DWORD dwCountDirs;						/* Counter for directories */
ULARGE_INTEGER u64CountBytes;			/* Counter for bytes */
ULARGE_INTEGER u64Temp;					/* A temporary counter */

	/* Initialize Variables */
	ptrStartNode = NULL;
	ptrNextNode = NULL;
	dwCount = 0;
	dwCountFiles = 0;
	dwCountDirs = 0;
	u64CountBytes.QuadPart = 0;

	/* Create szFullPath and szFullFileSpec */
	_tcscpy (szFullPath, szPath);
	if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
		_tcscat (szFullPath, _T("\\"));
	_tcscpy (szFullFileSpec, szFullPath);
	_tcscat (szFullFileSpec, szFilespec);

	/* Prepare the linked list, first node is allocated */
	ptrStartNode = malloc(sizeof(DIRFINDLISTNODE));
	if (ptrStartNode == NULL)
	{
#ifdef _DEBUG
		ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrStartNode!\n"));
#endif
		return 1;	/* Error cannot allocate memory for 1st object */
	}
	ptrNextNode = ptrStartNode;

	/* Collect the results for the current folder */
	hSearch = FindFirstFile(szFullFileSpec, &wfdFileInfo);
	do
	{
		if (hSearch != INVALID_HANDLE_VALUE)
		{
			/* Here we filter all the specified attributes */
			if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
				== (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
			{
				ptrNextNode->ptrNext = malloc(sizeof(DIRFINDLISTNODE));
				if (ptrNextNode->ptrNext == NULL)
				{
#ifdef _DEBUG
					ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrNextNode->ptrNext!\n"));
#endif
					while (ptrStartNode)
					{
						ptrNextNode = ptrStartNode->ptrNext;
						free(ptrStartNode);
						ptrStartNode = ptrNextNode;
						dwCount --;
					}
					return 1;
				}

				/* If malloc fails we go to next file in hope it works,
				   without braking the linked list! */
				if (ptrNextNode->ptrNext)
				{
					/* Copy the info of search at linked list */
					memcpy(&ptrNextNode->ptrNext->stFindInfo,
					       &wfdFileInfo,
					       sizeof(WIN32_FIND_DATA));

					/* If lower case is selected do it here */
					if (lpFlags->bLowerCase)
					{
						_tcslwr(ptrNextNode->ptrNext->stFindInfo.cAlternateFileName);
						_tcslwr(ptrNextNode->ptrNext->stFindInfo.cFileName);
					}

					/* Continue at next node at linked list */
					ptrNextNode = ptrNextNode->ptrNext;
					dwCount ++;

					/* Grab statistics */
					if (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
					{
						/* Directory */
						dwCountDirs++;
					}
					else
					{
						/* File */
						dwCountFiles++;
						u64Temp.HighPart = wfdFileInfo.nFileSizeHigh;
						u64Temp.LowPart = wfdFileInfo.nFileSizeLow;
						u64CountBytes.QuadPart += u64Temp.QuadPart;
					}
				}
			}
		}
	}while(FindNextFile(hSearch, &wfdFileInfo));
	FindClose(hSearch);

	/* Terminate list */
	ptrNextNode->ptrNext = NULL;

	/* Calculate and allocate space need for making an array of pointers */
	ptrFileArray = malloc(sizeof(LPWIN32_FIND_DATA) * dwCount);
	if (ptrFileArray == NULL)
	{
#ifdef _DEBUG
		ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrFileArray!\n"));
#endif
		while (ptrStartNode)
		{
			ptrNextNode = ptrStartNode->ptrNext;
			free(ptrStartNode);
			ptrStartNode = ptrNextNode;
			dwCount --;
		}		
		return 1;
	}

	/*
	 * Create an array of pointers from the linked list
	 * this will be used to sort and print data, rather than the list
	 */
	ptrNextNode = ptrStartNode;
	dwCount = 0;
	while (ptrNextNode->ptrNext)
	{
		*(ptrFileArray + dwCount) = &ptrNextNode->ptrNext->stFindInfo;
		ptrNextNode = ptrNextNode->ptrNext;
		dwCount++;
	}

	/* Sort Data if requested*/
	if (lpFlags->stOrderBy.sCriteriaCount > 0)
		QsortFiles(ptrFileArray, 0, dwCount-1,lpFlags);

	/* Print Data */
	DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);

	/* Free array */
	free(ptrFileArray);
	if (CheckCtrlBreak(BREAK_INPUT))
		return 1;


	/* Add statistics to recursive statistics*/
	recurse_dir_cnt += dwCountDirs;
	recurse_file_cnt += dwCountFiles;
	recurse_bytes.QuadPart += u64CountBytes.QuadPart;

	/* Do the recursive job if requested
	   the recursive is be done on ALL(indepent of their attribs)
	   directoried of the current one.*/
	if (lpFlags->bRecursive)
	{
		/* The new search is involving any *.* file */
		_tcscpy(szFullFileSpec, szFullPath);
		_tcscat(szFullFileSpec, _T("*.*"));
		hRecSearch = FindFirstFile (szFullFileSpec, &wfdFileInfo);
		do
		{
			if (hRecSearch != INVALID_HANDLE_VALUE)
			{
				/* We search for directories other than "." and ".." */
				if ((_tcsicmp(wfdFileInfo.cFileName, _T(".")) != 0) &&
				    (_tcsicmp(wfdFileInfo.cFileName, _T("..")) != 0 ) &&
				    (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
				{
					/* Concat the path and the directory to do recursive */
					_tcscpy(szFullFileSpec, szFullPath);
					_tcscat(szFullFileSpec, wfdFileInfo.cFileName);
					/* We do the same for tha folder */
					if (DirList(szFullFileSpec, szFilespec, pLine,lpFlags) != 0)
					{
						return 1;
					}
				}
			}
		}while(FindNextFile(hRecSearch,&wfdFileInfo));
		FindClose(hRecSearch);
	}

	/* Free linked list */
	while (ptrStartNode)
	{
		ptrNextNode = ptrStartNode->ptrNext;
		free(ptrStartNode);
		ptrStartNode = ptrNextNode;
		dwCount --;
	}

	return 0;
}



/*
 * dir
 *
 * internal dir command
 */
INT 
CommandDir(LPTSTR first, LPTSTR rest)
{
	TCHAR	dircmd[256];	/* A variable to store the DIRCMD enviroment variable */
	TCHAR	cDrive;
	TCHAR	szPath[MAX_PATH];
	TCHAR	szFilespec[MAX_PATH];
	LPTSTR*	params;
	INT		entries = 0;
	INT		nLine = 0;
	UINT	loop = 0;
	DIRSWITCHFLAGS stFlags;

	/* Initialize variables */
	cDrive = 0;
	recurse_dir_cnt = 0L;
	recurse_file_cnt = 0L;
	recurse_bytes.QuadPart = 0;

	/* Initialize Switch Flags < Default switches are setted here!> */
	stFlags.b4Digit = TRUE;
	stFlags.bBareFormat = FALSE;
	stFlags.bLowerCase = FALSE;
	stFlags.bNewLongList = TRUE;
	stFlags.bPause = FALSE;
	stFlags.bRecursive = FALSE;
	stFlags.bShortName = FALSE;
	stFlags.bTSeperator = TRUE;
	stFlags.bUser = FALSE;
	stFlags.bWideList = FALSE;
	stFlags.bWideListColSort = FALSE;
	stFlags.stTimeField.eTimeField = TF_MODIFIEDDATE;
	stFlags.stTimeField.bUnSet = FALSE;
	stFlags.stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
	stFlags.stAttribs.dwAttribVal = 0L;
	stFlags.stAttribs.bUnSet = FALSE;
	stFlags.stOrderBy.sCriteriaCount = 0;
	stFlags.stOrderBy.bUnSet = FALSE;

	nErrorLevel = 0;
	
	/* read the parameters from the DIRCMD environment variable */
	if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
		if (!DirReadParam(dircmd, &params, &entries, &stFlags))
		{
			nErrorLevel = 1;
			return 1;
		}

	/* read the parameters */
	if (!DirReadParam(rest, &params, &entries, &stFlags) || CheckCtrlBreak(BREAK_INPUT))
	{
		nErrorLevel = 1;
		return 1;
	}

	/* default to current directory */
	if(entries == 0) {
		if(!add_entry(&entries, &params, _T("."))) {
			nErrorLevel = 1;
			return 1;
		}
	}

	for(loop = 0; loop < entries; loop++)
	{
		/* parse the directory info */
		if (DirParsePathspec (params[loop], szPath, szFilespec) || CheckCtrlBreak(BREAK_INPUT))
		{
			nErrorLevel = 1;
			return 1;
		}

	/* <Debug :>
	   Uncomment this to show the final state of switch flags*/
	#ifdef _DEBUG
		{
			int i;
			ConOutPrintf(_T("Attributes mask/value %x/%x\n"),stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal  );
			ConOutPrintf(_T("(B) Bare format : %i\n"), stFlags.bBareFormat );
			ConOutPrintf(_T("(C) Thousand : %i\n"), stFlags.bTSeperator );
			ConOutPrintf(_T("(W) Wide list : %i\n"), stFlags.bWideList );
			ConOutPrintf(_T("(D) Wide list sort by column : %i\n"), stFlags.bWideListColSort );
			ConOutPrintf(_T("(L) Lowercase : %i\n"), stFlags.bLowerCase );
			ConOutPrintf(_T("(N) New : %i\n"), stFlags.bNewLongList );
			ConOutPrintf(_T("(O) Order : %i\n"), stFlags.stOrderBy.sCriteriaCount );
			for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
				ConOutPrintf(_T(" Order Criteria [%i]: %i (Reversed: %i)\n"),i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i] );
			ConOutPrintf(_T("(P) Pause : %i\n"), stFlags.bPause  );
			ConOutPrintf(_T("(Q) Owner : %i\n"), stFlags.bUser );
			ConOutPrintf(_T("(S) Recursive : %i\n"), stFlags.bRecursive );
			ConOutPrintf(_T("(T) Time field : %i\n"), stFlags.stTimeField.eTimeField );
			ConOutPrintf(_T("(X) Short names : %i\n"), stFlags.bShortName );
			ConOutPrintf(_T("Parameter : %s\n"), params[loop] );
		}
	#endif

		/* Print the drive header if the drive changed */
		if(cDrive != szPath[0] && !stFlags.bBareFormat) {
			if (!PrintDirectoryHeader (szPath, &nLine, &stFlags)) {
				nErrorLevel = 1;
				return 1;
			}

			cDrive = szPath[0];
		}
		

		/* do the actual dir */
		if (DirList (szPath, szFilespec, &nLine, &stFlags))
		{
			nErrorLevel = 1;
			return 1;
		}
	}

	/* print the footer */
	PrintSummary(szPath,
		recurse_file_cnt,
		recurse_dir_cnt,
		recurse_bytes,
		&nLine,
		&stFlags);
	
	return 0;
}

#endif

/* EOF */

⌨️ 快捷键说明

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