Code:
/**********************************************************************************************/
/** **/
/** FILE : myls.c **/
/** DESCRIPTION : function to list all the files in the current working directory **/
/** SUPPORTED SWITCHES : -l - List all file details **/
/** -a - List all files in directory **/
/** AUTHOR : Matt Conway (03500546) **/
/** DATE : 15/11/2005 **/
/** **/
/**********************************************************************************************/
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <locale.h>
#include <langinfo.h>
#include <stdint.h>
/* STATUS FLAGS USED TO DISCOVER SWITCHES USED */
#define AFLAG 0x01 /* 0x01 1 00000001 - set when -a is used */
#define LFLAG AFLAG << 1 /* 0x02 2 00000010 - set when -l is used */
#define XFLAG LFLAG << 1 /* 0x04 4 00000100 - set when no switches are used */
/* PROTOTYPES */
int openDirectory(char theProgram[], char thePath[], int whichSwitches);
void addDataToArray(int x, int y, DIR *theDir, int whichSwitches);
int sortCompare(const void *str1, const void *str2);
/* GLOBAL VARIABLES */
struct dirent *dir; /* pointer to file structure - that contains all file details */
int main(int argc, char **argv){
/* SET UP VARIABLES */
int theSwitches; /* int that contains multiple flags as bits */
int retVal = 0; /* return value from other functions if they were called. */
int i = 0; /* loop counter */
char *cwdir = "."; /* pointer the string pathname for the current working directory location */
int dirCount = 0; /* for counting the number of directories user wants listed */
/* Find out which switches the user wishes to use when displaying directory contents */
while ((retVal = getopt(argc, argv, ":al")) != -1) {
switch (retVal) {
case 'a': theSwitches = theSwitches |= AFLAG; /* set AFLAG bit */
break;
case 'l': theSwitches = theSwitches |= LFLAG; /* set LFLAG bit */
break;
case '?':
/* inform user that invalid switch was used */
printf("%s: USEAGE: <directory-name> <switch: -a -l>");
break;
}
}
/* NOTE: If this is put into case default, it does not get set!!! */
if (!(theSwitches & AFLAG) && !(theSwitches & LFLAG)){
theSwitches = theSwitches |= XFLAG; /* set XFLAG bit */
}
/* Did the user specify more than one directory to list contents of */
while (argv[i] != NULL){
if (i != 0){
if (strncmp(argv[i], "/", 1) == 0){
dirCount++;
retVal = openDirectory(argv[0], argv[i], theSwitches);
if (retVal != 0)
printf("%s: Cannot find directory %s, or it does not exist!\n",argv[0],argv[i], theSwitches);
}
else if (!strncmp(argv[i], "-", 1) == 0){
dirCount++;
retVal = openDirectory(argv[0], argv[i], theSwitches);
if (retVal != 0)
printf("%s: Cannot find directory %s, or it does not exist!\n",argv[0],argv[i],theSwitches);
}
}
i++;
} /* loop */
/* User did not specify a directory location, therefore, list current directory */
if (dirCount == 0) openDirectory(argv[0], cwdir, theSwitches);
return 0;
} /* main */
/**********************************************************************************************/
/** **/
/** FUNCTION : openDirectory **/
/** DESCRIPTION : Function to count the number of files / directories contained **/
/** within the directory that the user wishes to list, also, counts **/
/** the number of chars for the longest name **/
/** PARAMETERS : array containing the program name i.e. argv[0] **/
/** array containing the pathname of the directory **/
/** whichSwitch - each of the 8 bits is a flag turned on or off to **/
/** indicate whether or not a particular switch is used **/
/** AUTHOR : Matt Conway (03500546) **/
/** DATE : 18/11/2005 **/
/** **/
/**********************************************************************************************/
int openDirectory(char theProgram[], char thePath[], int whichSwitches){
int contentCount = 0; /* the number of dir(s) / file(s) within the directory to list */
int maxChars = 0; /* the number of chars for the longest dir / file name in directory to list */
DIR *theDirectory; /* pointer to the directory - used to get all the files within the cwd! */
theDirectory = opendir(thePath);
/* if (whichSwitches & AFLAG) printf("aflag = 1\n"); */
if (theDirectory){
if (thePath == ".")
printf("list of contents for: cwd\n");
else
printf("list of contents for: %s\n", thePath);
/* count the number of files and directories */
while ((dir = readdir(theDirectory))){
if (strncmp(dir->d_name, ".", 1) == 0){
if (whichSwitches & AFLAG){
contentCount++;
/* Check to see if the current name is longer than the longest so far */
if (strlen(dir->d_name) > maxChars)
maxChars = strlen(dir->d_name);
}
}
else{
contentCount++;
if (strlen(dir->d_name) > maxChars)
maxChars = strlen(dir->d_name);
}
}
/* strlen does not count the /0 string termination char, so make extra space for this! */
maxChars++;
/* rewind theDirectory (currently at EOD) to BOD for listing directory contents */
rewinddir(theDirectory);
/* Add directory data to the array */
addDataToArray(contentCount, maxChars, theDirectory, whichSwitches);
/* make theDirectory point to the first directory entry for listing*/
closedir(theDirectory);
return 0;
}
else
return 1;
} /* openDirectory */
/**********************************************************************************************/
/** **/
/** FUNCTION : addDataToArray **/
/** DESCRIPTION : Function to create a dynamic 2d array, large enough to store all **/
/** filenames and directory names that are contained within the **/
/** directory that is to be listed. It then adds all these names **/
/** to the array and sorts them into alphabetical order **/
/** PARAMETERS : x - the length of the array i.e. the number of file / dir names **/
/** y - the width of the array i.e. the number of chars of the longest **/
/** file / dir name **/
/** *theDir - pointer to the directory structure containing the file **/
/** and dir names **/
/** whichSwitch - each of the 8 bits is a flag turned on or off to **/
/** indicate whether or not a particular switch is used **/
/** AUTHOR : Matt Conway (03500546) **/
/** DATE : 19/11/2005 **/
/** **/
/**********************************************************************************************/
void addDataToArray(int x, int y, DIR *theDir, int whichSwitch){
char theArray[x][y];
int z = 0;
struct stat fileattrib;
struct passwd *pwd;
struct group *grp;
struct tm *tm;
char datestring[256];
int fileMode;
while ((dir = readdir(theDir)) != NULL){
if (strncmp(dir->d_name, "." , 1) == 0){
/* check to see if user is using option -a */
if (whichSwitch & AFLAG){
strcpy(theArray[z], dir->d_name);
z++;
}
}
else{
strcpy(theArray[z], dir->d_name);
z++;
}
} /* loop */
qsort((void*)theArray, (size_t)x, y, sortCompare);
/* Print the directory contents */
for (z = 0; z < x; z++){
/* Did the user request to print the files with -l option? */
if (whichSwitch & LFLAG){
/* Get the directory entries info */
if (stat(theArray[z], &fileattrib) == 0){
/* print a leading dash as start of file / directory permissions */
printf("-");
fileMode = fileattrib.st_mode;
/* Check owner permissions */
if ((fileMode & S_IRUSR) && (fileMode & S_IREAD))
printf("r");
else
printf("-");
if ((fileMode & S_IWUSR) && (fileMode & S_IWRITE))
printf("w");
else
printf("-");
if ((fileMode & S_IXUSR) && (fileMode & S_IEXEC))
printf("x");
else
printf("-");
/* Check group permissions */
if ((fileMode & S_IRGRP) && (fileMode & S_IREAD))
printf("r");
else
printf("-");
if ((fileMode & S_IWGRP) && (fileMode & S_IWRITE))
printf("w");
else
printf("-");
if ((fileMode & S_IXGRP) && (fileMode & S_IEXEC))
printf("x");
else
printf("-");
/* check other user permissions */
if ((fileMode & S_IROTH) && (fileMode & S_IREAD))
printf("r");
else
printf("-");
if ((fileMode & S_IWOTH) && (fileMode & S_IWRITE))
printf("w");
else
printf("-");
if ((fileMode & S_IXOTH) && (fileMode & S_IEXEC))
/* because this is the last permission, leave 3 blank spaces after print */
printf("x ");
else
/* because this is the last permission, leave 3 blank spaces after print */
printf("- ");
/* print number of links for the file / directory */
printf("%4d", fileattrib.st_nlink);
/* Print the owners name if it was found using getpwuid, if not, print the numeric code for owner */
if ((pwd = getpwuid(fileattrib.st_uid)) != NULL)
printf(" %-8.8s", pwd->pw_name);
else
printf(" %-8d", fileattrib.st_uid);
/* Print the group name if it was found using getgrgid, if not, print the numeric code for owner */
if ((grp = getgrgid(fileattrib.st_gid)) != NULL)
printf(" %-8.8s", grp->gr_name);
else
printf(" %-8d", fileattrib.st_gid);
/* Print file size */
printf(" %9jd", (intmax_t)fileattrib.st_size);
/* Print the date / time when the file was last updated */
tm = localtime(&fileattrib.st_mtime);
/* Get localized date string. */
strftime(datestring, sizeof(datestring), nl_langinfo(D_T_FMT), tm);
printf(" %s %s\n", datestring, theArray[z]);
}
else
printf("File attributes for %s cannot be found!\n",theArray[z]);
}
/* No -l switch being used, so just print the directory entry name */
else
printf("%s\n",theArray[z]);
} /* loop */
} /* addDataToArray */
/**********************************************************************************************/
/** **/
/** FUNCTION : sortCompare **/
/** DESCRIPTION : function to compare 2 strings and returns an integer less than, **/
/** equal to, or greater than zero if str1 is found, respectively, to **/
/** be less than, to mathc, or be greater than str2. **/
/** PARAMETERS : a pointer to the first string to be compared **/
/** a pointer to the second string to be compared **/
/** AUTHOR : Matt Conway (03500546) **/
/** DATE : 21/11/2005 **/
/** **/
/**********************************************************************************************/
int sortCompare(const void *str1, const void *str2){
return strcmp(str1,str2);
}