Copy codeThe Code is as follows :/*
Simulate the ls command to implement the parameter-tariRl. Some code is repeated and can be improved.
You can add Parameters Based on the program. The program idea is clear and easy to expand.
*/
# Include <stdio. h>
# Include <string. h>
# Include <stdlib. h>
# Include <sys/types. h>
# Include <unistd. h>
# Include <sys/stat. h>
# Include <dirent. h>
# Include <sys/ioctl. h>
# Include <pwd. h>
# Include <grp. h>
# Define LL (1 <0)/* with l parameter flag */
# Define IL (1 <1)/* with I parameter flag */
# Define RU (1 <2)/* with the R parameter flag */
# Define TL (1 <16)/* with the t parameter flag */
# Define AL (1 <17)/* with a parameter flag */
# Define RL (1 <18)/* with the r parameter flag */
# Define LENGTH 500/* maximum String LENGTH */
# Define MAX_FILE_COUNT 500/* Maximum length of the file list */
/* Function declaration */
Void error (char * error_message, int line );
Void display (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode );
Int file_list (char * path, struct stat * stalist, char (* namelist) [LENGTH], int mode );
Void display_simply (char (* namelist) [LENGTH], int n );
Void display_LL (struct stat * stalist, char (* namelist) [LENGTH], int n );
Void display_IL (struct stat * stalist, char (* namelist) [LENGTH], int n );
Void display_LL_IL (struct stat * stalist, char (* namelist) [LENGTH], int n );
Void display_RU (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode );
Void display_RU_LL (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode );
Void display_RU_IL (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode );
Void display_RU_IL_LL (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode );
/* Main function */
Int main (int argc, char ** argv)
{
Int I, j;
/* The first 16 digits of the mode are used to mark the parameters that can affect the display, and the last 16 digits are used to mark parameters that do not affect the output format. This program only uses 0-3, 16-18 bits. If you want to add parameters based on this program, you can use other unused bits.
The 0th bits of mode are 1, indicating the parameter with l, the 1st bits of mode are 1, indicating the parameter with I, and the 2nd bits of mode are 1, indicating the parameter with R, the 16th bits of mode are 1, indicating the t parameter. The 17th bits of mode are 1, indicating the parameter, and the 18th bits of mode are 1, indicating the r parameter */
Int mode = 0;
Char error_message [LENGTH] = {0};/* error message */
Char path [LENGTH] = {0};/* path */
Struct stat stalist [MAX_FILE_COUNT];/* array of file DETAILS */
Char namelist [MAX_FILE_COUNT] [LENGTH];/* array of file names */
Int flag = 0;/* determines whether a directory is specified */
Int count;/* Number of files */
/* Resolution parameter */
For (I = 1; I <argc; I ++ ){
If (argv [I] [0] = '-') {/* if it is an option parameter */
For (j = 1; j <strlen (argv [I]); j ++ ){
If (argv [I] [j] = 'l ')
Mode = mode | LL;
Else if (argv [I] [j] = 'I ')
Mode = mode | IL;
Else if (argv [I] [j] = 'R ')
Mode = mode | RU;
Else if (argv [I] [j] = 'R ')
Mode = mode | RL;
Else if (argv [I] [j] = 'A ')
Mode = mode | AL;
Else if (argv [I] [j] = 'T ')
Mode = mode | TL;
Else {
Snprintf (error_message, LENGTH, "no option of % c", argv [I] [j]);
Error (error_message ,__ LINE __);
}
}
} Else {/* the parameter is a directory or file */
If (flag = 1)
Error ("can not specify more then two dir or file" ,__ LINE __);
Else
Flag = 1;
If (argv [I] [0]! = '/') {/* Relative path */
Strcat (path, get_current_dir_name ());
Strcat (path ,"/");
Strncat (path, argv [I], strlen (argv [I]);
} Else/* absolute path */
Strcpy (path, argv [I]);
}
}
If (flag = 0)/* if no directory or file is specified, use the default directory */
Strcat (path, get_current_dir_name ());
/* Obtain files in the specified directory based on the mode */
Count = file_list (path, stalist, namelist, mode );
/* Display files by mode */
Display (stalist, namelist, count, mode );
Return 0;
}
/* Get the file list */
Int file_list (char * path, struct stat * stalist, char (* namelist) [LENGTH], int mode)
{
Int I = 0, index, j, k;
DIR * dir;
Struct dirent * ptr;
Char str [LENGTH];
Char nametemp [LENGTH];
Struct stat statemp;
If (stat (path, & stalist [0]) <0 ){
// Puts (path );
Error ("the specify file is not exist" ,__ LINE __);
}
If (S_ISDIR (stalist [0]. st_mode) {/* if the path points to a directory */
If (dir = opendir (path) = NULL) {/* Open the directory */
Sprintf (str, "can not open % s", path );
Error (str ,__ LINE __);
}
Chdir (path);/* change the current working directory to path */
I = 0;
While (ptr = readdir (dir ))! = NULL) {/* read all files in the directory in sequence */
If (ptr-> d_name [0] = '.'&&! (Mode & AL)/* ignore hidden files */
Continue;
/* Insert data in alphabetical order to the stalist array and namelist array */
For (j = I; j> 0; j --){
If (strcmp (ptr-> d_name, namelist [J-1])> 0)
Break;
}
For (k = I; k> j; k --){
Strcpy (namelist [k], namelist [k-1]);
Stalist [k] = stalist [k-1];
}
Strcpy (namelist [j], ptr-> d_name );
Stat (ptr-> d_name, & stalist [j]);
I ++;
If (I = MAX_FILE_COUNT)
Error ("file count beyond MAX_FILE_COUNT" ,__ LINE __);
}
Closedir (dir );
} Else {
J = strlen (path)-1;
While (j> = 0 & path [j]! = '/'){
J --;
}
If (j <0)
Error ("path error" ,__ LINE __);
J ++;
K = 0;
While (path [j]) {
Namelist [0] [k] = path [j];
J ++;
K ++;
}
Namelist [0] [k] = 0;
Return 1;
}
If (mode & TL) {/* sort by file modification time */
For (j = 0; j <I; j ++ ){
Index = j;
For (k = j + 1; k <I; k ++)
If (stalist [index]. st_mtime <stalist [k]. st_mtime ){
Index = k;
}
Statemp = stalist [j];
Stalist [j] = stalist [index];
Stalist [index] = statemp;
Strcpy (nametemp, namelist [j]);
Strcpy (namelist [j], namelist [index]);
Strcpy (namelist [index], nametemp );
}
}
If (mode & RL) {/* Reverse Order */
For (j = 0; j <I/2; j ++ ){
Strcpy (nametemp, namelist [j]);
Strcpy (namelist [j], namelist [i-j-1]);
Strcpy (namelist [i-j-1], nametemp );
Statemp = stalist [j];
Stalist [j] = stalist [i-j-1];
Stalist [i-j-1] = statemp;
}
}
Return I;
}
/* Select different functions for Display Based on mode */
Void display (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode)
{
/* Set the 16-bit high of mode to 0 */
Int m = mode & (1 <16)-1 );
Switch (m ){
Case 0:
Display_simply (namelist, n );
Break;
Case 1:
Display_LL (stalist, namelist, n );
Break;
Case 2:
Display_IL (stalist, namelist, n );
Break;
Case 3:
Display_LL_IL (stalist, namelist, n );
Break;
Case 4:
Display_RU (stalist, namelist, n, mode );
Break;
Case 5:
Display_RU_LL (stalist, namelist, n, mode );
Break;
Case 6:
Display_RU_IL (stalist, namelist, n, mode );
Break;
Case 7:
Display_RU_IL_LL (stalist, namelist, n, mode );
Break;
}
}
/* Simply display the file name without the display option */
Void display_simply (char (* namelist) [LENGTH], int n)
{
Int I, maxlength = 0, cols;
Struct winsize ts;
For (I = 0; I <n; I ++)
If (strlen (namelist [I])> maxlength)
Maxlength = strlen (namelist [I]);
/* Obtain the terminal size */
Ioctl (STDIN_FILENO, TIOCGWINSZ, & ts );
Cols = ts. ws_col;
Cols/= (maxlength + 1 );
// Lines = ts. ws_row;
For (I = 0; I <n; I ++ ){
If (I! = 0 & I % cols = 0)
Puts ("");
Printf ("% * s",-(maxlength + 1), namelist [I]);
}
Putchar ('\ n ');
}
/*-L parameter, displaying detailed file information */
Void display_LL (struct stat * stalist, char (* namelist) [LENGTH], int n)
{
Int I, mode;
Char * str;
For (I = 0; I <n; I ++ ){
Mode = stalist [I]. st_mode;
If (S_ISDIR (mode ))
Printf ("d ");
Else
Printf ("-");
If (mode & (1 <8 ))
Printf ("r ");
Else
Printf ("-");
If (mode & (1 <7 ))
Printf ("w ");
Else
Printf ("-");
If (mode & (1 <6 ))
Printf ("x ");
Else
Printf ("-");
If (mode & (1 <5 ))
Printf ("r ");
Else
Printf ("-");
If (mode & (1 <4 ))
Printf ("w ");
Else
Printf ("-");
If (mode & (1 <3 ))
Printf ("x ");
Else
Printf ("-");
If (mode & (1 <2 ))
Printf ("r ");
Else
Printf ("-");
If (mode & (1 <1 ))
Printf ("w ");
Else
Printf ("-");
If (mode & (1 <0 ))
Printf ("x ");
Else
Printf ("-");
Printf ("%-3d", stalist [I]. st_nlink );
Printf ("%-6 s", getpwuid (stalist [I]. st_uid)-> pw_name );
Printf ("%-6 s", getgrgid (stalist [I]. st_gid)-> gr_name );
Printf ("%-10d", stalist [I]. st_size );
Str = ctime (& stalist [I]. st_mtime );
Str [strlen (str)-2] = 0;
Printf ("% s", str );
Printf ("% s \ n", namelist [I]);
}
}
/*-I parameter, displaying the file name and node number */
Void display_IL (struct stat * stalist, char (* namelist) [LENGTH], int n)
{
Int I, maxlength = 0, cols;
Struct winsize ts;
For (I = 0; I <n; I ++)
If (strlen (namelist [I])> maxlength)
Maxlength = strlen (namelist [I]);
/* Obtain the terminal size */
Ioctl (STDIN_FILENO, TIOCGWINSZ, & ts );
Cols = ts. ws_col;
Cols/= (maxlength + 9 );
// Lines = ts. ws_row;
For (I = 0; I <n; I ++ ){
If (I! = 0 & I % cols = 0)
Puts ("");
Printf ("%-8d", stalist [I]. st_ino );
Printf ("% * s",-(maxlength + 1), namelist [I]);
}
Putchar ('\ n ');
}
/*-Li parameter, displaying detailed file information and node number */
Void display_LL_IL (struct stat * stalist, char (* namelist) [LENGTH], int n)
{
Int I, mode;
Char * str;
For (I = 0; I <n; I ++ ){
Printf ("%-8d", stalist [I]. st_ino );
Mode = stalist [I]. st_mode;
If (S_ISDIR (mode ))
Printf ("d ");
Else
Printf ("-");
If (mode & (1 <8 ))
Printf ("r ");
Else
Printf ("-");
If (mode & (1 <7 ))
Printf ("w ");
Else
Printf ("-");
If (mode & (1 <6 ))
Printf ("x ");
Else
Printf ("-");
If (mode & (1 <5 ))
Printf ("r ");
Else
Printf ("-");
If (mode & (1 <4 ))
Printf ("w ");
Else
Printf ("-");
If (mode & (1 <3 ))
Printf ("x ");
Else
Printf ("-");
If (mode & (1 <2 ))
Printf ("r ");
Else
Printf ("-");
If (mode & (1 <1 ))
Printf ("w ");
Else
Printf ("-");
If (mode & (1 <0 ))
Printf ("x ");
Else
Printf ("-");
Printf ("%-3d", stalist [I]. st_nlink );
Printf ("%-6 s", getpwuid (stalist [I]. st_uid)-> pw_name );
Printf ("%-6 s", getgrgid (stalist [I]. st_gid)-> gr_name );
Printf ("%-10d", stalist [I]. st_size );
Str = ctime (& stalist [I]. st_mtime );
Str [strlen (str)-2] = 0;
Printf ("% s", str );
Printf ("% s \ n", namelist [I]);
}
}
/* The-R parameter indicates that all files are displayed, including subdirectories under the directory */
Void display_RU (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode)
{
Int I, count;
Char path [LENGTH] = {0}, temp [LENGTH] = {0 };
Struct stat sta [MAX_FILE_COUNT];
Char name [MAX_FILE_COUNT] [LENGTH];
Puts (get_current_dir_name ());
Display_simply (namelist, n );
Putchar ('\ n ');
Strcpy (path, get_current_dir_name ());
For (I = 0; I <n; I ++ ){
If (strcmp (namelist [I], ".") = 0 | strcmp (namelist [I], "..") = 0)
Continue;
If (S_ISDIR (stalist [I]. st_mode )){
Strcpy (temp, path );
Strcat (path ,"/");
Strcat (path, namelist [I]);
Count = file_list (path, sta, name, mode );
Display_RU (sta, name, count, mode );
Strcpy (path, temp );
}
}
}
/*-Rl parameter: displays all files, including the details of subdirectories under the directory */
Void display_RU_LL (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode)
{
Int I, count;
Char path [LENGTH] = {0}, temp [LENGTH] = {0 };
Struct stat sta [MAX_FILE_COUNT];
Char name [MAX_FILE_COUNT] [LENGTH];
Puts (get_current_dir_name ());
Display_LL (stalist, namelist, n );
Putchar ('\ n ');
Strcpy (path, get_current_dir_name ());
For (I = 0; I <n; I ++ ){
If (strcmp (namelist [I], ".") = 0 | strcmp (namelist [I], "..") = 0)
Continue;
If (S_ISDIR (stalist [I]. st_mode )){
Strcpy (temp, path );
Strcat (path ,"/");
Strcat (path, namelist [I]);
Count = file_list (path, sta, name, mode );
Display_RU_LL (sta, name, count, mode );
Strcpy (path, temp );
}
}
}
/*-Ri parameter, which displays all files, including subdirectories and node numbers in the directory */
Void display_RU_IL (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode)
{
Int I, count;
Char path [LENGTH] = {0}, temp [LENGTH] = {0 };
Struct stat sta [MAX_FILE_COUNT];
Char name [MAX_FILE_COUNT] [LENGTH];
Puts (get_current_dir_name ());
Display_IL (stalist, namelist, n );
Putchar ('\ n ');
Strcpy (path, get_current_dir_name ());
For (I = 0; I <n; I ++ ){
If (strcmp (namelist [I], ".") = 0 | strcmp (namelist [I], "..") = 0)
Continue;
If (S_ISDIR (stalist [I]. st_mode )){
Strcpy (temp, path );
Strcat (path ,"/");
Strcat (path, namelist [I]);
Count = file_list (path, sta, name, mode );
Display_RU_IL (sta, name, count, mode );
Strcpy (path, temp );
}
}
}
/*-Ril parameter: displays all files, including the sub-directory details and node number in the directory */
Void display_RU_IL_LL (struct stat * stalist, char (* namelist) [LENGTH], int n, int mode)
{
Int I, count;
Char path [LENGTH] = {0}, temp [LENGTH] = {0 };
Struct stat sta [MAX_FILE_COUNT];
Char name [MAX_FILE_COUNT] [LENGTH];
Puts (get_current_dir_name ());
Display_LL_IL (stalist, namelist, n );
Putchar ('\ n ');
Strcpy (path, get_current_dir_name ());
For (I = 0; I <n; I ++ ){
If (strcmp (namelist [I], ".") = 0 | strcmp (namelist [I], "..") = 0)
Continue;
If (S_ISDIR (stalist [I]. st_mode )){
Strcpy (temp, path );
Strcat (path ,"/");
Strcat (path, namelist [I]);
Count = file_list (path, sta, name, mode );
Display_RU_IL_LL (sta, name, count, mode );
Strcpy (path, temp );
}
}
}
// Error handling function
Void error (char * error_message, int line)
{
Char str [5];
Sprintf (str, "% d:", line );
Strcat (str, error_message );
Perror (str );
Exit (EXIT_FAILURE );
}