P
Poster Matt
First of all if the code below is a mess on your screen, or if you'd prefer to
read it on a web page, then it's up on pastie - here: http://pastie.org/816917
I'm back doing some C coding on Linux, having not coded in C for 15 years...
My project needs the total file size of all the files in a directory tree, so I
wrote the function below. It calls itself recursively (wow, haven't needed to
use recursion in a while!). The function works fine, but I have a couple of
questions.
1) Am I freeing the memory correctly?
2) It seems like a lot of code to do something so simple. I had a look at
basically the same thing I wrote in C# a couple of years ago (which uses the
same recursive logic but uses only 10 lines of code). Is the code below more
lengthy than need be? In other words, have I missed an easier way of doing it,
by my choice of C standard library functions?
3) Any glaring mistakes in the code? I know I'm not checking malloc's return
value (I'll use my own mallocOrDie() function later), and ditch the printf()s.
Thanks all.
// Returns the size in bytes of a dir tree.
// Make sure char* dirName ends in a '/'.
long GetDirectoryTreeSize(char* dirName)
{
// Total in bytes
long total = 0;
DIR *directory;
struct dirent *dirItem;
struct stat statbuf;
// Open dir for reading or exit()
directory = opendir(dirName);
if (directory == NULL)
{
printf("\nCan't open dir: %s", dirName);
exit(1);
}
// Loop through files and subdirs.
while ((dirItem = readdir(directory)) != NULL)
{
// If item is a file, make full path and add its file size.
if (dirItem->d_type != DT_DIR)
{
// Make full path to the file.
int fullPathLen = strlen(dirName) + strlen(dirItem->d_name) + 1;
char* fullPath = (char*) malloc(fullPathLen);
sprintf(fullPath, "%s%s", dirName, dirItem->d_name);
// Call stat(), put file stats in statbuf.
int ret = stat(fullPath, &statbuf);
// On sucess stat() returns 0.
if (ret == 0)
total += statbuf.st_size;
printf("\n%s - %ld", fullPath, statbuf.st_size);
free(fullPath);
fullPath = NULL;
}
// If item is a dir, but not '.' or '..', make recursive call.
else
{
if ( (strcmp(dirItem->d_name, ".") != 0) &&
(strcmp(dirItem->d_name, "..") != 0) )
{
// Make full path to subdir, add a final '/'.
int fullPathToSubDirLen = strlen(dirName) +
strlen(dirItem->d_name) + 2;
char* fullPathToSubDir = (char*) malloc(fullPathToSubDirLen);
sprintf(fullPathToSubDir, "%s%s/", dirName, dirItem->d_name);
printf("\nNew Dir: %s", fullPathToSubDir);
// Make recursive call.
total += GetDirectoryTreeSize(fullPathToSubDir);
free(fullPathToSubDir);
fullPathToSubDir = NULL;
}
}
}
closedir(directory);
return total;
}
read it on a web page, then it's up on pastie - here: http://pastie.org/816917
I'm back doing some C coding on Linux, having not coded in C for 15 years...
My project needs the total file size of all the files in a directory tree, so I
wrote the function below. It calls itself recursively (wow, haven't needed to
use recursion in a while!). The function works fine, but I have a couple of
questions.
1) Am I freeing the memory correctly?
2) It seems like a lot of code to do something so simple. I had a look at
basically the same thing I wrote in C# a couple of years ago (which uses the
same recursive logic but uses only 10 lines of code). Is the code below more
lengthy than need be? In other words, have I missed an easier way of doing it,
by my choice of C standard library functions?
3) Any glaring mistakes in the code? I know I'm not checking malloc's return
value (I'll use my own mallocOrDie() function later), and ditch the printf()s.
Thanks all.
// Returns the size in bytes of a dir tree.
// Make sure char* dirName ends in a '/'.
long GetDirectoryTreeSize(char* dirName)
{
// Total in bytes
long total = 0;
DIR *directory;
struct dirent *dirItem;
struct stat statbuf;
// Open dir for reading or exit()
directory = opendir(dirName);
if (directory == NULL)
{
printf("\nCan't open dir: %s", dirName);
exit(1);
}
// Loop through files and subdirs.
while ((dirItem = readdir(directory)) != NULL)
{
// If item is a file, make full path and add its file size.
if (dirItem->d_type != DT_DIR)
{
// Make full path to the file.
int fullPathLen = strlen(dirName) + strlen(dirItem->d_name) + 1;
char* fullPath = (char*) malloc(fullPathLen);
sprintf(fullPath, "%s%s", dirName, dirItem->d_name);
// Call stat(), put file stats in statbuf.
int ret = stat(fullPath, &statbuf);
// On sucess stat() returns 0.
if (ret == 0)
total += statbuf.st_size;
printf("\n%s - %ld", fullPath, statbuf.st_size);
free(fullPath);
fullPath = NULL;
}
// If item is a dir, but not '.' or '..', make recursive call.
else
{
if ( (strcmp(dirItem->d_name, ".") != 0) &&
(strcmp(dirItem->d_name, "..") != 0) )
{
// Make full path to subdir, add a final '/'.
int fullPathToSubDirLen = strlen(dirName) +
strlen(dirItem->d_name) + 2;
char* fullPathToSubDir = (char*) malloc(fullPathToSubDirLen);
sprintf(fullPathToSubDir, "%s%s/", dirName, dirItem->d_name);
printf("\nNew Dir: %s", fullPathToSubDir);
// Make recursive call.
total += GetDirectoryTreeSize(fullPathToSubDir);
free(fullPathToSubDir);
fullPathToSubDir = NULL;
}
}
}
closedir(directory);
return total;
}