View Full Version : Implementing "ls -al"
pdstatha
03-05-2002, 10:43 AM
Can someone do me a favour and check if the following code works, i'm away from my linux machine. The following code should hopefully produce an output similar to that of the "ls -al" command.
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#define SIZE 256
char* workdir(){
size_t size = FILENAME_MAX;
while(1){
char* wdbuf = (char*)malloc(size);
if(getcwd(wdbuf,size) == wdbuf)
return wdbuf;
free(wdbuf);
if(errno != ERANGE)return 0;
size *=2;
}
}
void printDetails(char *filename){
struct passwd *my_passwd;
struct group *my_group;
struct stat sbuf;
struct tm *strtime;
int fdes;
unsigned char type ='?';
unsigned char usr[] = "---";
unsigned char grp[] = "---";
unsigned char oth[] = "---";
unsigned char uid[9], gid[9];
unsigned char mod[13];
mode_t mode;
char* curdir;
time_t now;
int year;
/*Concatenate dir names*/
curdir = workdir();
strcat(curdir,"/");
strcat(curdir,filename);
/*stat the final dir name*/
if(stat(curdir,&sbuf) != -1){
if(S_ISLNK(sbuf.st_mode)){
if(lstat(curdir,&sbuf) == -1){
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
}else if(S_ISREG(sbuf.st_mode)){
if(fstat(fdes,&sbuf) == -1){
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
}
}else{
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
/*format information*/
mode = sbuf.st_mode;
if( S_ISLNK( mode ) ) type = 'l'; /*symlink*/
else if( S_ISDIR ( mode ) ) type = 'd'; /*directory*/
else if( S_ISCHR ( mode ) ) type = 'c'; /*character raw device*/
else if( S_ISBLK ( mode ) ) type = 'b'; /*block raw device*/
else if( S_ISFIFO( mode ) ) type = 'p'; /*named pipe*/
else if( S_ISSOCK( mode ) ) type = 's'; /*Unix domain socket*/
else if( S_ISREG ( mode ) ) type = '-'; /*regular file*/
if( mode & S_IRUSR ) usr[0] = 'r';
if( mode & S_IWUSR ) usr[1] = 'w';
if( mode & S_IXUSR ) usr[2] = 'x';
if( mode & S_ISUID ) usr[2] = 's'; /* set UID bit*/
if( mode & S_IRGRP ) grp[0] = 'r';
if( mode & S_IWGRP ) grp[1] = 'w';
if( mode & S_IXGRP ) grp[2] = 'x';
if( mode & S_ISGID ) grp[2] = 's'; /* set GID bit*/
if( mode & S_IROTH ) oth[0] = 'r';
if( mode & S_IWOTH ) oth[1] = 'w';
if( mode & S_IXOTH ) oth[2] = 'x';
my_passwd = getpwuid(sbuf.st_uid);
if(my_passwd)
strncpy(uid,my_passwd->pw_name,8);
else
snprintf(uid,9,"%d",sbuf.st_uid);
my_group = getgrgid(sbuf.st_gid);
if(my_group)
strncpy(gid,my_group->gr_name,8);
else
snprintf(gid,9,"%d",sbuf.st_gid);
time(&now);
year = localtime(&now)->tm_year;
strtime = localtime(&sbuf.st_ctime);
if(strtime->tm_year == year)
strftime(mod,13,"%b %e %R",strtime);
else
strftime(mod,13,"%b %e %Y",strtime);
/*print the details*/
printf("%c%s%s%s %4u %-8s %81u %12s %s\n",
type,usr,grp,oth,sbuf.st_nlink,
uid,gid,sbuf.st_size,mod,filename);
free(curdir);
}
int main(int argc, char **argv) {
int fdes,count,index;
char *curdir;
struct stat sbuf;
struct dirent **direntp;
curdir = workdir();
if(argv[1] != '\0'){
if(stat(argv[1], &sbuf) != -1){
if(S_ISDIR(sbuf.st_mode)){ /* Is a directory */
count = scandir(argv[1],&direntp,NULL,alphasort);
if(count){
for(index=0; index<count; ++index){
printDetails(direntp[index]->d_name);
free(direntp[index]);
}
}else{
fprintf(stderr,"Can't open %s\n",argv[1]);
exit(EXIT_FAILURE);
}
}else if(S_ISREG(sbuf.st_mode)){ /* Is a regular file */
if((fdes = open(argv[1],O_RDONLY)) != ENOENT){
printDetails(argv[1]);
close(fdes);
}else
printf("Can't open %s reg\n",argv[1]);
}
}else
printf("Can't stat %s\n", argv[1]);
}else{
if(stat(curdir,&sbuf) !=-1){
count = scandir(curdir,&direntp,NULL,alphasort);
if(count){
for(index=0; index<count; ++index){
printDetails(direntp[index]->d_name);
free(direntp[index]);
}
}else{
fprintf(stderr,"Can't open %s\n",curdir);
exit(EXIT_FAILURE);
}
}else
fprintf(stderr,"Can't stat %s\n",curdir);
}
free(curdir);
free(direntp);
return EXIT_SUCCESS;
}
howdy >pdstatha<,
i didnt spend a whole bunch of time with this but this is what gcc2.96 had to say when i tryed to compile your code.:)
cd /home/Mike/
make -k dir
g++ dir.cpp -o dir
dir.cpp: In function `void printDetails (char *)':
dir.cpp:93: cannot convert `unsigned char *' to `char *' for argument
`1' to `strncpy (char *, const char *, unsigned int)'
dir.cpp:95: cannot convert `unsigned char *' to `char *' for argument
`1' to `snprintf (char *, unsigned int, const char *, ...)'
dir.cpp:99: cannot convert `unsigned char *' to `char *' for argument
`1' to `strncpy (char *, const char *, unsigned int)'
dir.cpp:101: cannot convert `unsigned char *' to `char *' for argument
`1' to `snprintf (char *, unsigned int, const char *, ...)'
dir.cpp:107: cannot convert `unsigned char *' to `char *' for argument
`1' to `strftime (char *, unsigned int, const char *, const tm *)'
dir.cpp:109: cannot convert `unsigned char *' to `char *' for argument
`1' to `strftime (char *, unsigned int, const char *, const tm *)'
dir.cpp: In function `int main (int, char **)':
dir.cpp:127: parse error before `)'
dir.cpp:140: confused by earlier errors, bailing out
make: *** [dir] Error 1
Compilation exited abnormally with code 2 at Wed Mar 6 22:31:03
sorry.
M.R.
beg_g
03-11-2002, 06:38 AM
Heyy all,
Umm itld, now you weren't trying to compile C code with a C++ compiler, now were you?? :-) (!)
That aside, I found only one bug which prevented the program from compiling, on line 126, change those to double quotes i.e argv[1] != ""
Still your program does not run, I get segmentation fault, could there be something shady with your code (I haven't really analysed it but here is the output:
beg_g@space:~/test > gcc -o lsal lsal.c
beg_g@space:~/test > lsal /home
Segmentation fault
beg_g@space:~/test >
I called the file lsal.c
Cheers.
howdy,
Umm itld, now you weren't trying to compile C code with a C++ compiler, now were you?? :-) (!)
hey nobody is perfect.:o
itld asks himself if this is the only stupid newbie trick he will perform today :D
M.R.
Unregistered
03-19-2002, 04:18 PM
I just had to write some code for class and it was interesting when I saw this topic. Here is my code:
mars:$ more writels2.cpp
#include <stdio.h>
#include <dirent.h>
#include <iostream.h>
#include <grp.h>
#include <iomanip.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <time.h>
void showpermiss(struct stat &s, char *p);
int main( int argc, char** argv )
{
char *p[20];
char buff[20];
char p2[20];
char mdate[30];
char formating = ' ';
int counting=1;
cin.getline(buff,20);
p[0] = strtok(buff," ");
DIR *dirp;
struct dirent *direntp;
dirp = opendir(".");
//if(p[0] == NULL)
// {
while((direntp = readdir(dirp)) != NULL)
{
if (strcmp(buff, "dir")==0)
{
struct stat s;
stat(direntp->d_name,&s);
showpermiss(s, p2);
cout<<p2<<" ";
// cout<<s.st_mode;
cout<<setw(3)<<s.st_nlink;
struct passwd *pw = getpwuid(s.st_uid);
cout<<setw(9)<<pw->pw_name;
struct group * gr = getgrgid(s.st_gid);
cout<<setw(8)<<gr->gr_name;
cout<<setw(8)<<s.st_size;
strcpy(mdate, ctime(&s.st_mtime));
mdate[16] = 0;
cout<<" "<<mdate<< " ";
//<<ctime(&s.st_mtime);
cout<<setw(2)<<direntp->d_name<<endl;
}//endif
else if (strcmp(buff, "-w")==0)
{
cout<<direntp->d_name<<endl;
}//end if
else if (strcmp(buff, "-pause")==0)
{
if (counting < 26)
{
struct stat s;
stat(direntp->d_name,&s);
showpermiss(s, p2);
cout<<p2<<" ";
cout<<setw(3)<<s.st_nlink;
struct passwd *pw = getpwuid(s.st_uid);
cout<<setw(9)<<pw->pw_name;
struct group * gr = getgrgid(s.st_gid);
cout<<setw(8)<<gr->gr_name;
cout<<setw(8)<<s.st_size;
strcpy(mdate, ctime(&s.st_mtime));
mdate[16] = 0;
cout<<" "<<mdate<< " ";//<<ctime(&s.st_mtime);
cout<<setw(2)<<direntp->d_name<<endl;
counting++;
}//end if
}//end if
else
if (strcmp(buff, "-F")==0)
{
struct stat s;
stat(direntp->d_name,&s);
cout<<direntp->d_name;
if(s.st_mode & S_IFDIR)
cout<<"/"<<endl;
else
if(s.st_mode & S_IFIFO)
cout<<"|"<<endl;
else
if(s.st_mode & S_IFLNK)
cout<<"@"<<endl;
else
if(s.st_mode & S_IFDOOR)
cout<<">"<<endl;
else
if(s.st_mode & S_IFSOCK)
cout<<"="<<endl;
else
if((s.st_mode & S_IFREG) && (s.st_mode & S_IXUSR) || (s.st_mode &S_IXUSR) || (s.st_mode & S_IXGRP) || (s.st_mode & S_IXOTH))
cout<<"*"<<endl;
else
cout<<"?"<<endl;
}//end if
}//end while
closedir(dirp);
// return 0;
}
void showpermiss(struct stat &s, char *p)
{
if ( s.st_mode & S_IFIFO) p[0] = 'p';
else
if ( s.st_mode & S_IFCHR ) p[0] = 'c';
else
if ( s.st_mode & S_IFDIR ) p[0] = 'd';
else
if ( s.st_mode & S_IFBLK ) p[0] = 'b';
else
p[0] = '-';
p[1] = ( s.st_mode & S_IRUSR ) ? 'r' : '-';
p[2] = ( s.st_mode & S_IWUSR ) ? 'w' : '-';
p[3] = ( s.st_mode & S_IXUSR ) ? 'x' : '-';
p[4] = ( s.st_mode & S_IRGRP ) ? 'r' : '-';
p[5] = ( s.st_mode & S_IWGRP ) ? 'w' : '-';
p[6] = ( s.st_mode & S_IXGRP ) ? 'x' : '-';
p[7] = ( s.st_mode & S_IROTH ) ? 'r' : '-';
p[8] = ( s.st_mode & S_IWOTH ) ? 'w' : '-';
p[9] = ( s.st_mode & S_IXOTH ) ? 'x' : '-';
p[10] = '\0';
}
howdy,
i compiled this with one error, i had to comment out this section, S_IFDOOR undeclared??
else
if(s.st_mode & S_IFDOOR)
cout<<">"<<endl;
on but it will not do anything, i am using a command line like this
./similar /home/Mike
but nothing happens. how is this used??
M.R.
pdstatha
03-19-2002, 05:36 PM
Just an update, i finally got the code working and here it is if ur interested.
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
/*prototypes*/
char* workdir(void);
void printDetails(char* filename,char* path);
int main(int argc, char **argv) {
int count,index;
char *curdir;
struct stat sbuf;
struct dirent **direntp;
if(argv[1] != '\0'){
if(stat(argv[1], &sbuf) != -1){
if(S_ISDIR(sbuf.st_mode)){ /* Is a directory */
count = scandir(argv[1],&direntp,NULL,alphasort);
if(count){
char path[FILENAME_MAX];
for(index=0; index<count; ++index){
strcpy(path,argv[1]);
printDetails(direntp[index]->d_name,path);
free(direntp[index]);
}
}else{
fprintf(stderr,"Can't open %s\n",argv[1]);
exit(EXIT_FAILURE);
}
}else
printDetails(argv[1],NULL);
}else
fprintf(stderr,"Can't stat %s\n", argv[1]);
}else{
curdir = workdir();
printf("%s\n",curdir);
if(stat(curdir,&sbuf) !=-1){
count = scandir(curdir,&direntp,NULL,alphasort);
if(count){
for(index=0; index<count; ++index){
printDetails(direntp[index]->d_name,NULL);
free(direntp[index]);
}
}else{
fprintf(stderr,"Can't open %s\n",curdir);
exit(EXIT_FAILURE);
}
}else{
fprintf(stderr,"Can't stat %s\n",curdir);
exit(EXIT_FAILURE);
}
free(curdir);
}
return EXIT_SUCCESS;
}
char* workdir(){
while(1){
char* wdbuf = (char*)malloc(FILENAME_MAX);
if(getcwd(wdbuf,FILENAME_MAX) == wdbuf)
return wdbuf;
free(wdbuf);
if(errno != ERANGE){
fprintf(stderr,"Out of range\n");
return 0;
}
}
}
void printDetails(char *filename,char *path){
struct passwd *my_passwd; /*User details*/
struct group *my_group; /*Group details*/
struct stat sbuf; /*File details*/
struct tm *strtime; /*Time format*/
int fdes; /*File descriptor*/
unsigned char type ='?'; /*File type*/
unsigned char usr[] = "---"; /*User Permissions*/
unsigned char grp[] = "---"; /*Group Permissions*/
unsigned char oth[] = "---"; /*Other Permissions*/
unsigned char uid[9], gid[9]; /*User name and Group name*/
unsigned char mod[13]; /*Time information*/
mode_t mode; /*Used to determine type and permission bits*/
char* curdir; /*Used to hold the current working directory*/
char* buf; /*Used to hold a link location*/
time_t now; /*Used to format the time*/
int year; /*Used to format the time*/
/*If path is null stat by the curdir*/
if(path == NULL){
curdir = workdir();
strcat(curdir,"/");
strcat(curdir,filename);
if(stat(curdir,&sbuf) != -1){
if(S_ISLNK(sbuf.st_mode)){
if(readlink(curdir,buf,(size_t)FILENAME_MAX) != -1){
if(lstat(buf,&sbuf) == -1){
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
}else
fprintf(stderr,"Can't readlink %s\n",filename);
}else if(S_ISREG(sbuf.st_mode)){
if((fdes = open(curdir,O_RDONLY)) != ENOENT){
if(fstat(fdes,&sbuf) == -1){
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
close(fdes);
}else{
fprintf(stderr,"Can't open %s\n",filename);
return;
}
}
}else{
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
free(curdir);
/*Otherwise stat by the path provided*/
}else{
strcat(path,"/");
strcat(path,filename);
if(stat(path,&sbuf) != -1){
if(S_ISLNK(sbuf.st_mode)){
if(readlink(path,buf,(size_t)FILENAME_MAX) != -1){
if(lstat(buf,&sbuf) == -1){
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
}else
fprintf(stderr,"Can't readlink %s\n",filename);
}else if(S_ISREG(sbuf.st_mode)){
if((fdes = open(path,O_RDONLY)) != ENOENT){
if(fstat(fdes,&sbuf) == -1){
fprintf(stderr,"Can't stat %s\n",filename);
return;
}
close(fdes);
}else{
fprintf(stderr,"Can't open %s\n",filename);
return;
}
}
}else{
fprintf(stderr,"Path: %s\n",path);
fprintf(stderr,"Can't stat %s\n",curdir);
return;
}
}
/*Get file types and permissions*/
mode = sbuf.st_mode;
if( S_ISLNK( mode ) ){ type = 'l'; /*symlink*/ printf("%c\n",type);}
else if( S_ISDIR ( mode ) ) type = 'd'; /*directory*/
else if( S_ISCHR ( mode ) ) type = 'c'; /*character raw device*/
else if( S_ISBLK ( mode ) ) type = 'b'; /*block raw device*/
else if( S_ISFIFO( mode ) ) type = 'p'; /*named pipe*/
else if( S_ISSOCK( mode ) ) type = 's'; /*Unix domain socket*/
else if( S_ISREG ( mode ) ) type = '-'; /*regular file*/
if( mode & S_IRUSR ) usr[0] = 'r';
if( mode & S_IWUSR ) usr[1] = 'w';
if( mode & S_IXUSR ) usr[2] = 'x';
if( mode & S_ISUID ) usr[2] = 's'; /* set UID bit*/
if( mode & S_IRGRP ) grp[0] = 'r';
if( mode & S_IWGRP ) grp[1] = 'w';
if( mode & S_IXGRP ) grp[2] = 'x';
if( mode & S_ISGID ) grp[2] = 's'; /* set GID bit*/
if( mode & S_IROTH ) oth[0] = 'r';
if( mode & S_IWOTH ) oth[1] = 'w';
if( mode & S_IXOTH ) oth[2] = 'x';
/*Get user information*/
my_passwd = getpwuid(sbuf.st_uid);
if(my_passwd != NULL){
strncpy(uid,my_passwd->pw_name,8);
uid[8] = '\0';
}else
snprintf(uid,9,"%d",sbuf.st_uid);
/*Get group information*/
my_group = getgrgid(sbuf.st_gid);
if(my_group != NULL){
strncpy(gid,my_group->gr_name,8);
gid[8] = '\0';
}else
snprintf(gid,9,"%d",sbuf.st_gid);
/*Format the time to readable form*/
time(&now);
year = localtime(&now)->tm_year;
strtime = localtime(&sbuf.st_ctime);
if(strtime->tm_year == year)
strftime(mod,13,"%b %e %R",strtime);
else
strftime(mod,13,"%b %e %Y",strtime);
/*print the details*/
printf("%c%s%s%s %d %s %s %d\t%s %s\n",
type,usr,grp,oth,sbuf.st_nlink,
uid,gid,sbuf.st_size,mod,filename);
}
howdy pdstatha,
that works very well. compiled and ran with no errors using gcc 2.96/emacs.
M.R.:)
Unregistered
03-19-2002, 08:05 PM
Originally posted by itld
howdy,
i compiled this with one error, i had to comment out this section, S_IFDOOR undeclared??
else
if(s.st_mode & S_IFDOOR)
cout<<">"<<endl;
on but it will not do anything, i am using a command line like this
./similar /home/Mike
but nothing happens. how is this used??
M.R.
How's it going? What are you running on? I'm running Unix on SunOS 5.8
Unregistered
03-19-2002, 08:14 PM
when i tried to compile his code, it said that alphasort was undeclared??
Unregistered
03-19-2002, 08:17 PM
Originally posted by itld
on but it will not do anything, i am using a command line like this
./similar /home/Mike
but nothing happens. how is this used??
M.R. [/B]
OH YEAH...to run it, i used a.out and then typed -F to get the formatting characters. to use each other others (dir, -w, and -pause) run a.out again and try to type the command. dont try to run multiples though LoL cuz it wont work :o)
a.out
-F
a.out
-pause
a.out
-w
a.out
dir
pdstatha
03-20-2002, 04:39 AM
Don't know why it does that, it compiles just fine for me. There is one problem with the code though, for some the code which detects a symbolic link does not work correctly. Any ideas??
vBulletin® v3.7.0, Copyright ©2000-2009, Jelsoft Enterprises Ltd.