Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
05-11-2004, 02:30 PM
|
#1
|
Member
Registered: Apr 2003
Posts: 178
Rep:
|
listing files in a directory
I got the code below from the book The C Programming Language by
Brian W. Kernighan on page 181.
I ran the program below and it did list the file named "text_file.txt"
root:/home# ./directory_1 /home/text_file.txt
1766 /home/text_file.txt
but when I ran the program using just the home directory, it goes into an infinite loop and it never list any files
root:/home# ./directory_1 /home/
fsize: can 't access /home////////////////////////////////////////////////////////////////////////////////////////////////////////¸
fsize: can 't access /home////////////////////////////////////////////////////////////////////////////////////////////////////////Ì
fsize: can 't access /home/////////////////////////////////////////////////////////////////////
==================================
Code:
#include <stdio.h> /* standard library. a minimum requirement */
#include <stdlib.h> /* for oct_long = strtoul (six_oct_char, NULL, 8) */
#include <string.h> /* for strcmp, strcpy functions */
#include <fcntl.h>
#include <sys/types.h> /* for pid_t pid; */
#include <signal.h> /* for kill(pid, SIGTERM); function */
#include <dirent.h> /* for DIR *d = opendir("/proc"); declaration */
#include <sys/stat.h> /* for struct stat sb; */
typedef struct
{
long ino;
char name[NAME_MAX + 1];
} Dirent;
char *name;
void fsize(char *);
/************************************************/
void dirwalk(char *, void (*fcn)(char *));
/* fsize: print size of file "name" */
void fsize(char *name)
{
struct stat stbuf;
if (stat(name, &stbuf) == -1)
{
fprintf(stderr, "fsize: can 't access %s\n", name);
return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, fsize);
printf("%8ld %s\n", stbuf.st_size, name);
}
/************************************************/
#define MAX_PATH 1024
/* dirwalk: apply fcn to all files in dir */
void dirwalk(char *dir, void (*fcn)(char *))
{
char name[MAX_PATH];
Dirent *dp;
DIR *dfd;
if ( (dfd = opendir(dir)) == NULL )
{
fprintf(stderr, "dirwalk: can 't open %s\n", dir);
return;
}
while ( (dp = readdir(dfd)) != NULL )
{
if (strcmp(dp -> name, ".") == 0 || strcmp(dp -> name, "..") == 0)
continue; /* skip self and parent directory */
if (strlen(dir) + strlen(dp -> name) + 2 > sizeof(name))
fprintf(stderr, "dirwalk: name %s/%s too long\n", dir, dp->name);
else
{
sprintf(name, "%s/%s", dir, dp -> name);
(*fcn)(name);
} /* if-then-else */
} /* while loop */
closedir(dfd);
}
/************************************************/
/* print file sizes */
main(int argc, char **argv)
{
if (argc == 1)
fsize(".");
else
while (--argc > 0)
fsize(*++argv);
return 0;
}
|
|
|
05-11-2004, 03:29 PM
|
#2
|
Senior Member
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536
Rep:
|
Change this:
Code:
typedef struct
{
long ino;
char name[NAME_MAX + 1];
} Dirent;
to:
Code:
typedef struct dirent Dirent;
And then change everywhere you see this: "dp -> name" to "dp -> d_name"
Then you get:
Code:
#include <stdio.h> /* standard library. a minimum requirement */
#include <stdlib.h> /* for oct_long = strtoul (six_oct_char, NULL, 8) */
#include <string.h> /* for strcmp, strcpy functions */
#include <fcntl.h>
#include <sys/types.h> /* for pid_t pid; */
#include <signal.h> /* for kill(pid, SIGTERM); function */
#include <dirent.h> /* for DIR *d = opendir("/proc"); declaration */
#include <sys/stat.h> /* for struct stat sb; */
typedef struct dirent Dirent;
char *name;
void fsize(char *);
/************************************************/
void dirwalk(char *, void (*fcn)(char *));
/* fsize: print size of file "name" */
void fsize(char *name)
{
struct stat stbuf;
if (stat(name, &stbuf) == -1)
{
fprintf(stderr, "fsize: can 't access %s\n", name);
return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, fsize);
printf("%8ld %s\n", stbuf.st_size, name);
}
/************************************************/
#define MAX_PATH 1024
/* dirwalk: apply fcn to all files in dir */
void dirwalk(char *dir, void (*fcn)(char *))
{
char name[MAX_PATH];
Dirent *dp;
DIR *dfd;
if ( (dfd = opendir(dir)) == NULL )
{
fprintf(stderr, "dirwalk: can 't open %s\n", dir);
return;
}
while ( (dp = readdir(dfd)) != NULL )
{
if (strcmp(dp -> d_name, ".") == 0 || strcmp(dp -> d_name, "..") == 0)
continue; /* skip self and parent directory */
if (strlen(dir) + strlen(dp -> d_name) + 2 > sizeof(name))
fprintf(stderr, "dirwalk: name %s/%s too long\n", dir, dp->d_name);
else
{
sprintf(name, "%s/%s", dir, dp -> d_name);
(*fcn)(name);
} /* if-then-else */
} /* while loop */
closedir(dfd);
}
/************************************************/
/* print file sizes */
main(int argc, char **argv)
{
if (argc == 1)
fsize(".");
else
while (--argc > 0)
fsize(*++argv);
return 0;
}
Last edited by Hko; 05-11-2004 at 03:37 PM.
|
|
|
05-11-2004, 04:01 PM
|
#3
|
Member
Registered: Apr 2003
Posts: 178
Original Poster
Rep:
|
reply to Hko
Thank you hko. I got it solved.
Last edited by Linh; 05-11-2004 at 04:18 PM.
|
|
|
05-11-2004, 04:19 PM
|
#4
|
Senior Member
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536
Rep:
|
Quote:
it works, except that when it goes into a subdirectory, it started to create that subdirectory many level deep. Forexample if it goes to /home/public/
it will create /home/public/public/public/public/public/public/public/...
and then /home/Flash/Flash/Flash/Flash/Flash/Flash/Flash/Flash/...
and so forth.
|
I can not reproduce that.
On my computer it works fine.
|
|
|
05-11-2004, 05:19 PM
|
#5
|
Member
Registered: Apr 2003
Posts: 178
Original Poster
Rep:
|
reply to Hko
Hi Hko. Thank you for your help.
Now that the code run, please help me understand a few things.
On page 180-181 of the book "The C Programming Language" Second Edition by Brian W. Kernighan, it list a bunch of declaration in order to run
a program listing files in a directory as shown in this thread. Some of that declaration are listed below.
==============================
Code:
You told me to change from:
typedef struct
{
long ino;
char name[NAME_MAX + 1];
} Dirent;
to: typedef struct dirent Dirent;
1) Under what condition would I used the above structure declaration,
instead of the one that you have suggested which is
typedef struct dirent Dirent ?
==============================
2) Page 180, listed these. Under what condition would I used all of these
declaration ?
typedef struct
{
long ino;
char name[NAME_MAX + 1];
} Dirent;
typedef struct
{
int fd;
Dirent d;
} DIR;
DIR *opendir(char *dirname);
Dirent *readdir(DIR *dfd);
void closedir (DIR *dfd);
==============================
On page 181, the book said to use
#define S_IFMT 0160000
3) What is the number 0160000 stand for ?
4) Is the number 0160000 a Hexadecimal value ?
5) root:/home# gcc -o directory_1 directory_1.c
directory_1.c:14: warning: `S_IFMT' redefined
/usr/include/sys/stat.h:101: warning: this is the location
of the previous definition
5) When I compiled as shown above, it resulted in an error.
Under what condition would I use
#define S_IFMT 0160000 ?
==============================
6) I also use
#include <syscalls.h>
When I compiled it gives me an error.
root:/home# gcc -o directory_1 directory_1.c
directory_1.c:7: syscalls.h: No such file or directory
6) Where would I find the library syscalls.h ?
Last edited by Linh; 05-11-2004 at 05:22 PM.
|
|
|
05-11-2004, 06:09 PM
|
#6
|
Senior Member
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536
Rep:
|
Quote:
You told me to change from:
typedef struct
{
long ino;
char name[NAME_MAX + 1];
} Dirent;
to: typedef struct dirent Dirent;
1) Under what condition would I used the above structure declaration,
instead of the one that you have suggested which is
typedef struct dirent Dirent ?
|
Just don't put it directly in your .c file. The declaration differs between different versions of UNIX, and UNIX-clones like Linux. The header file "dirent.h" contains the correct declaration for the UNIX flavour it gets compiled on.
So, just #include <dirent.h> and you're fine.
When you change every " Dirent" in the program to " struct dirent" you can also delete my line ("typedef struct dirent Dirent;")
Quote:
2) Page 180, listed these. Under what condition would I used all of these
declaration ?
typedef struct
{
long ino;
char name[NAME_MAX + 1];
} Dirent;
typedef struct
{
int fd;
Dirent d;
} DIR;
DIR *opendir(char *dirname);
Dirent *readdir(DIR *dfd);
void closedir (DIR *dfd);
|
Same answer: Just do not put them in your .c file yourself. Just #include the header, and the right "Dirent", DIR, struct, or whatever for your Linux/UNIX flavour will be declared. This is one of the most important reasons why header files exist.
Quote:
On page 181, the book said to use
#define S_IFMT 0160000
3) What is the number 0160000 stand for ?
|
It's bitmask to use for 'isolating' the bits that indicate the type-of-file from the struct member "st_mode". This is needed when testing for the type of file because "st_mode" contains more infomation than only the type. Use "blabla & S_IFMT" to use the mask on "blabla".
Quote:
4) Is the number 0160000 a Hexadecimal value ?
|
No. It's an octal number, because it start with a '0'. A hexadecimal number would start with "0x".
Quote:
5) root:/home# gcc -o directory_1 directory_1.c
directory_1.c:14: warning: `S_IFMT' redefined
/usr/include/sys/stat.h:101: warning: this is the location
of the previous definition
5) When I compiled as shown above, it resulted in an error.
Under what condition would I use
#define S_IFMT 0160000 ?
|
Same answer: The right #define S_IFMT for your Linux/UNIX version is in the header. Do not #define it yourself. See the error-message:
"/usr/include/sys/stat.h:101: warning: this is the location of the previous definition"
It says it has been defined before you did. In the header "stat.h" that is...
Quote:
6) I also use
#include <syscalls.h>
When I compiled it gives me an error.
root:/home# gcc -o directory_1 directory_1.c
directory_1.c:7: syscalls.h: No such file or directory
6) Where would I find the library syscalls.h ?
|
#include <sys/syscall.h> probably. (Error in the book? Or is Linux different than UNIX's in this case? don't know...) Maybe you can delete that line without problems.
By the way: "syscall.h" is a header file, not a library.
Last edited by Hko; 05-11-2004 at 06:34 PM.
|
|
|
05-12-2004, 09:27 AM
|
#7
|
Member
Registered: Apr 2003
Posts: 178
Original Poster
Rep:
|
reply
Thank you Hko for your explanation.
|
|
|
05-17-2004, 04:35 AM
|
#8
|
LQ Newbie
Registered: Apr 2004
Location: Paris, France
Distribution: Mandrake 9.2
Posts: 5
Rep:
|
Just an observation... I'm on the Kernighan and Ritchie myself, and it's an amazing reference. Most of the code examples don't compile as is though, so I'd be inclined to confirm that there are differences between UNIX and Linux in this respect. That was all!
|
|
|
All times are GMT -5. The time now is 10:25 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|