ls (my own implementation)
Little talk about 'ls' (since I have very small knowledge about it):
ls - list directory contents.
Know details about 'ls' in linux man page: http://unixhelp.ed.ac.uk/CGI/man-cgi?ls
Little talk about coding:
Probably I wouldn't write this code in my entire life unless I got it as my lab assignment :D. It was my 2nd year System Programming lab assignment. However, at first, it seemed very disgusting and painful task to me. But after started coding, it was fun to write the code.
I tried to make my 'ls' as like as linux's 'ls' implementation. Since I was not very familiar with linux, before doing this assignment, firstly I checked out all the options provided by the 'ls' process. Actually, I had to learn about all the functionalities it has :D.
Implementation:
I used c++ as the programming language. I have the name of a directory or file in dirent->d_name & and by using lstat() function, I retrieved all the information about a file or directory.
- I saved each file or directory name and statistics in a vector.
- Applying printing format given by the OPTIONS.
- Print the corresponding information.
Here is my coding.........
/* * Course: CSE-326 System Programming Lab * Assignment No: 02 * Assignment Name: ls — list directory contents * SYNOPSIS: ls [-AacdFfhiklnoqRrSstuw1] [file . . .] * Author: Sayef Azad Sakin * Roll: 1563 * Language: c++ */ #ifndef BLOCKSIZE #define BLOCKSIZE 512 #endif #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <vector> #include <dirent.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <climits> #include <algorithm> using namespace std; #define eps 1e-11 #define mx 1000 struct files{ string name, full_path; struct stat st; files(string ps, string s, struct stat &ss){ full_path = ps; name = s; st = ss; } }; vector < files > name, dir_name[10], dir_path, rfile, rdir; vector < files >:: iterator it; bool flag[30]; int tot_dir; char chk[] = {'A','a','c','d','F','f','h','i','k','l','n','o','q','R','r','S','s','t','u','w','1'}; bool comp(const files &a, const files &b){ if(flag[15]){//-S if(a.st.st_size == b.st.st_size){ if(flag[17]){//-t if(a.st.st_mtime == b.st.st_mtime)return (a.name<b.name); return (a.st.st_mtime < b.st.st_mtime); } return (a.name<b.name); } return (a.st.st_size > b.st.st_size); } if(flag[17]){//-t if(a.st.st_mtime == b.st.st_mtime)return (a.name<b.name); return (a.st.st_mtime < b.st.st_mtime); } if(flag[2]){//-c if(a.st.st_ctime == b.st.st_ctime)return (a.name<b.name); return (a.st.st_ctime < b.st.st_ctime); } if(flag[18]){//-u if(a.st.st_atime == b.st.st_atime)return (a.name<b.name); return (a.st.st_atime < b.st.st_atime); } return (a.name<b.name); } int getfile(files fdes); int chkflag(char *str); void print(const files fdes); int main(int argc, char **argv){ int argpos, i, sz; bool ok; char path[mx], cwd[mx]; dirent *dirp; DIR *dp; struct stat f_stat; //initialize(); //parsing starts here ok = 0; for(argpos = 1; argpos < argc; argpos++){ if(argv[argpos][0]=='-'){ if(chkflag(argv[argpos])==-1){puts("argument error");return 2;} } else{ if (lstat(argv[argpos], &f_stat) == -1){puts("statistics error");return -1;} if(S_ISREG(f_stat.st_mode) || !strcmp(argv[argpos],".") || !strcmp(argv[argpos],".."))rfile.push_back(files(argv[argpos],argv[argpos],f_stat)); else if(S_ISDIR(f_stat.st_mode))rdir.push_back(files(argv[argpos],argv[argpos],f_stat)); ok = 1; } } if(!ok){ if( !getcwd(cwd,mx) ) return 1; if( !(dp = opendir(cwd)) ){puts("error on opening current directory");return 3;} while( (dirp = readdir(dp)) ){ strcpy(path,"."); strcat(path,"/"); strcat(path,dirp->d_name); if (lstat(path, &f_stat) == -1){puts("statistics error");return -1;} if(S_ISREG(f_stat.st_mode) || !strcmp(dirp->d_name,".") || !strcmp(dirp->d_name,".."))rfile.push_back(files(path,dirp->d_name,f_stat)); else if(S_ISDIR(f_stat.st_mode))rdir.push_back(files(path,dirp->d_name,f_stat)); } if( closedir(dp) < 0 ){puts("can't close directory");return -1;} } //parsing ends here //sorting starts here sort(rfile.begin(),rfile.end(),comp); sort(rdir.begin(),rdir.end(),comp); if(flag[14]){//-r reverse(rfile.begin(),rfile.end()); reverse(rdir.begin(),rdir.end()); } //sorting ends here sz = rfile.size(); for(i=0;i<sz;i++) print(rfile[i]); if(!ok || flag[3]){//-d sz = rdir.size(); for(i=0;i<sz;i++) print(rdir[i]); return 0; } puts(""); sz = rdir.size(); if(ok || flag[13]){//-R for(i=0;i<sz;i++){ cout << rdir[i].name << ":(under this direcotry) " << endl; if(getfile(rdir[i])==-1)return 5; } } return 0; } int getfile(files fdes){ dirent *dirp; DIR *dp; vector < files > tfile, tdir; struct stat file_stat; char path[mx], tpath[mx]; int sz, i; strcpy(path,fdes.full_path.c_str()); if( !(dp = opendir(path)) ){puts("error on opening directory");return -1;} while( (dirp = readdir(dp)) ){ strcpy(tpath,path); sz = strlen(tpath); if(tpath[sz-1]!='/'){ tpath[sz] = '/'; tpath[sz+1] = 0; } strcat(tpath,dirp->d_name); //printf("%s\n",tpath); if (lstat(tpath, &file_stat) == -1){puts("statistics error");return -1;} if(S_ISREG(file_stat.st_mode) || !strcmp(dirp->d_name,".") || !strcmp(dirp->d_name,".."))tfile.push_back(files(tpath,dirp->d_name,file_stat)); else if(S_ISDIR(file_stat.st_mode))tdir.push_back(files(tpath,dirp->d_name,file_stat)); } if( closedir(dp) < 0 ){puts("can't close directory");return -1;} //sorting starts here sort(tfile.begin(),tfile.end(),comp); sort(tdir.begin(),tdir.end(),comp); if(flag[14]){//-r reverse(tfile.begin(),tfile.end()); reverse(tdir.begin(),tdir.end()); } //sorting ends here sz = tfile.size(); for(i=0;i<sz;i++) print(tfile[i]); sz = tdir.size(); for(i=0;i<sz;i++) print(tdir[i]); puts(""); if(flag[3])return 0;//-d if(flag[13]){ sz = tdir.size(); for(i=0;i<sz;i++){ cout << tdir[i].name << ":(under this direcotry) " << endl; if(getfile(tdir[i])==-1)return -1; } } return 0; } int chkflag(char *str){ bool ok; int i,j; for(i = 1;str[i]; i++){ if(str[i]=='R' && flag[3])continue; ok = 0; for(j=0;j<21;j++){ if(chk[j]=='h' && str[i]=='k')flag[j] = 0; else if(chk[j]=='k' && str[i]=='h')flag[j] = 0; else if(chk[j]=='1' && str[i]=='l')flag[j] = 0; else if(chk[j]=='l' && str[i]=='1')flag[j] = 0; else if(chk[j]=='c' && str[i]=='u')flag[j] = 0; else if(chk[j]=='u' && str[i]=='c')flag[j] = 0; else if(chk[j]=='q' && str[i]=='w')flag[j] = 0; else if(chk[j]=='w' && str[i]=='q')flag[j] = 0; else if(chk[j]=='R' && str[i]=='d')flag[j] = 0; if(chk[j]==str[i]){ok=1;break;} } if(ok)flag[j] = 1; else return -1; } return 0; } void print(const files fdes){ double sz; struct tm *ts; char ptime[20]; struct passwd *ps; struct group *gr; sz = fdes.st.st_size; if(!flag[1] && (fdes.name == "." || fdes.name == ".."))return; if(flag[7])printf("%u ",fdes.st.st_ino);//-i if(flag[16]){//-s sz = fdes.st.st_blocks*512; if(!flag[6] && !flag[8]){ sz /=1024; printf("%5.0lf ",ceil(sz)); } } if(flag[6] && flag[16]){//-h if(sz>1073741824 || fabs(sz-1073741824)<eps){ sz /= 1073741824; printf("%.1lfG ",sz+eps); } else if(sz>1048576 || fabs(sz-1048576)<eps){ sz /= 1048576; printf("%.1lfM ",sz+eps); } else if(sz>1024 || fabs(sz-1024)<eps){ sz /= 1024; printf("%.1lfK ",sz+eps); } else printf("%.0lf ",sz); } if(flag[8] && flag[16]){//-k sz /= 1024; printf("%5.0lf ",ceil(sz)); } if(flag[9] || flag[10] || flag[13]){//-l & -n //file mode //entry type if(S_ISBLK(fdes.st.st_mode))printf("b"); else if(S_ISCHR(fdes.st.st_mode))printf("c"); else if(S_ISDIR(fdes.st.st_mode))printf("d"); else if(S_ISLNK(fdes.st.st_mode))printf("l"); else if(S_ISSOCK(fdes.st.st_mode))printf("s"); else if(S_ISFIFO(fdes.st.st_mode))printf("p"); else if(S_ISREG(fdes.st.st_mode))printf("-"); //owner permission printf((fdes.st.st_mode & S_IRUSR)?"r":"-"); printf((fdes.st.st_mode & S_IWUSR)?"w":"-"); if((S_ISREG(fdes.st.st_mode) || S_ISDIR(fdes.st.st_mode)) && fdes.st.st_mode & 0111) printf((fdes.st.st_mode & S_ISUID)?"s":"x"); else printf((fdes.st.st_mode & S_ISUID)?"S":"-"); //group permission printf((fdes.st.st_mode & S_IRGRP)?"r":"-"); printf((fdes.st.st_mode & S_IWGRP)?"w":"-"); if((S_ISREG(fdes.st.st_mode) || S_ISDIR(fdes.st.st_mode)) && fdes.st.st_mode & 0111) printf((fdes.st.st_mode & S_ISGID)?"s":"x"); else printf((fdes.st.st_mode & S_ISGID)?"S":"-"); //other permission printf((fdes.st.st_mode & S_IROTH)?"r":"-"); printf((fdes.st.st_mode & S_IWOTH)?"w":"-"); if((S_ISREG(fdes.st.st_mode) || S_ISDIR(fdes.st.st_mode)) && fdes.st.st_mode & 0111) printf((fdes.st.st_mode & S_ISVTX)?"t":"-"); else printf((fdes.st.st_mode & S_ISVTX)?"T":"-"); //number of links printf(" %u",fdes.st.st_nlink); //user name & group name if(flag[10])printf(" %5u%5u",fdes.st.st_uid,fdes.st.st_gid); else{ ps = getpwuid(fdes.st.st_uid); printf(" %s ",ps->pw_name); if(!flag[13]){ gr = getgrgid(fdes.st.st_gid); printf(" %s",gr->gr_name); } } //no of bytes sz = fdes.st.st_size; if(flag[6]){//-h if(sz>1073741824 || fabs(sz-1073741824)<eps){ sz /= 1073741824; printf("%10.1lfG ",sz+eps); } else if(sz>1048576 || fabs(sz-1048576)<eps){ sz /= 1048576; printf("%10.1lfM ",sz+eps); } else if(sz>1024 || fabs(sz-1024)<eps){ sz /= 1024; printf("%10.1lfK ",sz+eps); } else printf("%10.0lf ",sz); } else if(flag[8]){//-k sz /= 1024; printf("%10.0lf ",ceil(sz)); } else printf("%10.0lf ",sz); //year-month-day hh:mm ts = localtime(&fdes.st.st_mtime); strftime(ptime, sizeof(ptime), "%Y-%m-%d %H:%M", ts); printf("%s ", ptime); } cout << fdes.name; if(flag[4]){//-F if(S_ISDIR(fdes.st.st_mode))printf("/"); else if(S_ISREG(fdes.st.st_mode) && fdes.st.st_mode & 0111)printf("*"); else if(S_ISLNK(fdes.st.st_mode))printf("@"); //else if(S_IFWHT(fdes.st.st_mode))printf("@"); else if(S_ISSOCK(fdes.st.st_mode))printf("="); else if(S_ISFIFO(fdes.st.st_mode))printf("|"); } puts(""); }