Code: C
//Header Files
#include "filelist.h"
/**
* main () this is used to receive path at the command line.
*
* @Param [in] argc contains the number of strings in a command prompt.
*
* @Param [in] *argv[] contains the address of the strings.
*
*/
int main(int argc, char *argv[])
{
char* DirSpec; // pointer to a character declaration.
int traversal; //variable declaration.
char* substring; // pointer to a character declaration.
argv[1]="c:";
argv[2]="/s";
argc=2;
printf ("Target directory is %s.\n", argv[1]);
DirSpec=(char*)calloc ( strlen(argv[1])+1,sizeof(char)); //memory allocation for the path.
strcpy(DirSpec,argv[1]); //copies the argv[1] to path.
printf("Name \t\t\t\t Dir/Size \t Created \t Attributes");
if(strcmp(argv[2],"/s")==0){
traversal=INTERNALTRAVERSING; //sets the traversal type to internal.
}else{
traversal=FIRSTLEVELTRAVERSING; //sets the traversal type to first level.
}
//checks if the path contains an extension.
if(FindMatch(DirSpec)!=1){
if(GetFileAttributes(DirSpec)==FILE_ATTRIBUTE_DIRECTORY){
substring=NULL;
strcat(DirSpec,"\\*");
}else{
substring=GetSubstring(DirSpec); //retrieves the extensio of the path in a substring.
}
}else{
substring=NULL;
}
WalkFolder(DirSpec,traversal,substring); //calls the walk folder with path,traversal type and extension.
_getch();
free(DirSpec); //frees the memory allocated for path.
return (0);
}
/**
* Display(WIN32_FIND_DATA *pFindFileData) () is used to display the details of the file or folder.
*
* @Param [in] *pFindFileData contains the file data.
*
*/
void Display(WIN32_FIND_DATA *pFindFileData)
{
LPSYSTEMTIME lpst;
lpst=(LPSYSTEMTIME)calloc(1,sizeof(SYSTEMTIME)); //allocates memory for lpst.
FileTimeToSystemTime(&pFindFileData->ftCreationTime,lpst); //converts the time to system time.
if(pFindFileData->nFileSizeLow==0)
printf ("\n %s \t\t\t\t <Dir>\t\t ", pFindFileData->cFileName);
else
printf("\n %s \t %d \t ",pFindFileData->cFileName,pFindFileData->nFileSizeLow);
printf("%d/%d/%d %d:%d:%d \t ",lpst->wDay,lpst->wMonth,lpst->wYear,lpst->wHour,lpst->wMinute,lpst->wSecond);
PrintFileAttribute(pFindFileData->dwFileAttributes);
free(lpst); //frees the memory allocated for lpst.
}
/**
* WalkFolder (char* pPath,BOOL pSub_folders,char* pSubstr)() used to insert an integer into the specified stack.
*
* @Param [in] pValue contains the value which is to be pushed into the buffer.
*
* @Return int 0 when pop fails else the element which was poped out.
*/
void WalkFolder (char* pPath,BOOL pSub_folders,char* pSubstr)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind; //contains the handle returned by the path.
DWORD dwError; //contains the last error occurred.
char ** allpath; //pointer to the array which stores all new paths.
int index=0; //contains the total count of paths stored.
int i; //used for looping.
static int no_of_files=0; //contains the number of files.
static int no_of_folders=0; //contains the number of folders.
printf("\n .................................................................");
printf("\n The display is for the path %s \n ", pPath);
allpath=(char **)calloc(DEFAULTSIZE,sizeof(char*)); //allocates memory for allpath.
hFind= INVALID_HANDLE_VALUE; //assigness invalid handle value to hFind.
hFind = FindFirstFile(pPath, &FindFileData); //assigns the first file handle to hFind.
if (hFind == INVALID_HANDLE_VALUE && pSub_folders!=INTERNALTRAVERSING ) {
printf ("Invalid file handle. Error is %u\n", GetLastError());
} else if(hFind!= INVALID_HANDLE_VALUE && pSubstr !=NULL){
PrintFileInfo(hFind,&FindFileData,&no_of_files);
}
if(pSubstr !=NULL && pSub_folders==INTERNALTRAVERSING){
RemoveSubString(pPath,pSubstr); //calls RemoveSubString function to remove the extension from it.
hFind = FindFirstFile(pPath, &FindFileData); //assigns the first file handle to hFind.
}
do{
if(pSubstr==NULL){
Display(&FindFileData); //calls the display function to print the file and folder details.
}
if(FindFileData.nFileSizeLow==0 && (strcmp(FindFileData.cFileName,".")!=0)
&& (strcmp(FindFileData.cFileName,"..")!=0)&& pSub_folders==INTERNALTRAVERSING){
if((index+1)%DEFAULTSIZE==0 && index>0){
allpath=(char **)realloc(allpath,(index+DEFAULTSIZE)); //reallocates memory.
}
allpath[index]=GetNewPath(pPath,FindFileData.cFileName,pSubstr); //retrieves the new path and stores it in allpath.
index++;
}else if(FindFileData.nFileSizeLow!=0 && pSubstr==NULL){
no_of_files++; //increments the number of files
}if(FindFileData.nFileSizeLow==0 ){
no_of_folders++; //increments the number of folders.
}
}while (FindNextFile(hFind, &FindFileData) != 0 ); //works until next file exists.
for(i=0;i<index;i++){
WalkFolder(allpath[i],pSub_folders,pSubstr); //calls back the walk folder with the new path.
}
dwError = GetLastError(); //stores the last error
FindClose(hFind); //closes the file opened,whose handle is passed.
if (dwError != ERROR_NO_MORE_FILES) {
printf ("FindNextFile error. Error is %u\n", dwError); //prints the error message.
}
}
/**
* GetNewPath(char* pPath,char *pFileName,char* pType)() used to retrieve the path for internal traversing.
*
* @Param [in] pPath contains the path from which new path is to be retrieved.
*
* @Param [in] pFileName contains the file from which new path is to be retrieved.
*
* @Param [in] pType contains a substring ,if the path is of specific type,else NULL.
*
* @Return char* returns the new path.
*/
char * GetNewPath(char* pPath,char *pFileName,char* pType)
{
char* path; //contains the new path.
if(pType==NULL){
path=(char*)calloc(strlen(pPath)+strlen(pFileName)+1,sizeof(char)); //memory allocation for path ,if there is no extension.
}else{
path=(char*)calloc(strlen(pPath)+strlen(pFileName)+strlen(pType)+1,sizeof(char));//memory allocation for path ,if there is extension.
}
strcpy(path,pPath); //copies the previous sent path to path.
path[strlen(path)-1]='\0'; //adds a '\0' at the end of the path.
strcat(path,pFileName); //adds the filename to the path.
if(pType==NULL){
strcat(path,"\\*"); //adds \* if there is no extension.
}else{
strcat(path,pType); //adds the extension at the back of the path.
}
return path; //returns the path .
}
/**
* FindMatch(char* pPath)() used to find aparticular match pattern in the string.
*
* @Param [in] pPath contains the path from which match is to be found.
*
* @Return int returns true if match is found,else false.
*/
int FindMatch(char* pPath)
{
int i;
i=strlen(pPath)-1; //calculates the length of the path
if(pPath[i]=='*'&& pPath[i-1]=='\\'){ //checks if the path contains \*
return TRUE; //returns true if \* is found.
}
return FALSE; //returns false if \* not found.
}
/**
* GetSubstring(char* pPath)() used to get the extension of the path as substring.
*
* @Param [in] pPath contains the path for which extension is to be found.
*
* @Return char* returns the substring.
*/
char* GetSubstring(char* pPath)
{
char* substring; //contains the substring i.e the extension.
int i; //used for looping.
int length; //contains the length for the extension.
for(i=strlen(pPath)-1;i>0;i--){
if(pPath[i]=='\\') //checks for first \ from back and breaks.
break;
}
length=strlen(pPath)+1-i; //calculates the length of the extension.
substring=(char*)calloc(length,sizeof(char)); //allocates memory for the substring.
strcpy(substring,(pPath+i)); //copies the extension to substring.
return substring; //returns the extension.
}
/**
* RemoveSubString(char *pPath,char* pSubstr)() used to remove the substring from the path.
*
* @Param [in] pPath contains the path for which extension is to be removed.
*
* @Param [in] pSubstr contains the extension which is to be removed.
*
*/
void RemoveSubString(char *pPath,char* pSubstr)
{
int len; //contains the length of the path without extension.
len=strlen(pPath)-strlen(pSubstr)+4; //calculates the new length.
pPath=(char*)realloc(pPath,(len)); //reallocates memory for path.
pPath[len-4]='\0'; //appends a '\0' to end the path.
strcat(pPath,"\\*."); //adds a \. at then sn dof the path.
}
/**
* PrintFileInfo(HANDLE hFind,WIN32_FIND_DATA *FindFileData,int *no_of_files)() used to print the file details.
*
* @Param [in] hFind contains the hanle of the file .
*
* @Param [in] FindFileData used to find the data about the file .
*
* @Param [in] *no_of_files contains the number of files .
*
*/
void PrintFileInfo(HANDLE hFind,WIN32_FIND_DATA *FindFileData,int *no_of_files)
{
do{
Display(FindFileData); //calls the display function to print the file and folder details.
*no_of_files++; //calculates the number of files.
}while(FindNextFile(hFind, FindFileData) != 0 ); //works until no more files are left.
}
/**
* PrintFileAttribute(DWORD fileAttribute)() used to print the attributes of the file.
*
* @Param [in] pFileattribute contains the attributes of the file.
*
*/
void PrintFileAttribute(DWORD pFileattribute )
{
int index; ///< holds the index of attribute array
int flag; ///< holds the flag value
///< attribute array holds the file all attributes
int attribute[12] = {FILE_ATTRIBUTE_READONLY,
FILE_ATTRIBUTE_HIDDEN,
FILE_ATTRIBUTE_SYSTEM,
FILE_ATTRIBUTE_DIRECTORY,
FILE_ATTRIBUTE_ARCHIVE,
FILE_ATTRIBUTE_DEVICE,
FILE_ATTRIBUTE_NORMAL,
FILE_ATTRIBUTE_TEMPORARY,
FILE_ATTRIBUTE_SPARSE_FILE,
FILE_ATTRIBUTE_REPARSE_POINT,
FILE_ATTRIBUTE_COMPRESSED,
FILE_ATTRIBUTE_OFFLINE};
//Assign starting value zero to count
index =0;
//printf("\t");
//loop continue upto fileattribute greaterthan attribute[count]
while (pFileattribute >=(unsigned long) attribute[index]) {
//flag holds attribute value
flag = pFileattribute & attribute[index++];
switch (flag) {
//if the file attribute is readonly
case FILE_ATTRIBUTE_READONLY:
printf( "R ");
break;
//if the file attribute is hidden
case FILE_ATTRIBUTE_HIDDEN:
printf( "H ");
break;
//if the file attribute is system
case FILE_ATTRIBUTE_SYSTEM:
printf( "S ");
break;
//if the file attribute is archive
case FILE_ATTRIBUTE_ARCHIVE:
printf( "A ");
break;
//if the file attribute is device
case FILE_ATTRIBUTE_DEVICE:
printf( "D ");
break;
//if the file attribute is normal
case FILE_ATTRIBUTE_NORMAL:
printf( "N ");
break;
//if the file attribute is temporary
case FILE_ATTRIBUTE_TEMPORARY:
printf( "T ");
break;
//if the file attribute is sparse file
case FILE_ATTRIBUTE_SPARSE_FILE:
printf( "SF ");
break;
//if the file attribute is reparse point
case FILE_ATTRIBUTE_REPARSE_POINT:
printf( "RP ");
break;
//if the file attribute is compressed
case FILE_ATTRIBUTE_COMPRESSED:
printf( "C ");
break;
//if the file attribute is offline
case FILE_ATTRIBUTE_OFFLINE:
printf( "O ");
break;
}
}
}