Article View: comp.unix.programmer
Article #3428readir() II
From: frank
Date: Wed, 27 Jan 2010 07:21
Date: Wed, 27 Jan 2010 07:21
333 lines
8092 bytes
8092 bytes
Hello again comp.unix.programer,gnu.gcc.help
I would like to develop a small C utility that does something that a
mortensen child can use. If I don't get it done before the end of
january, then it's not a x-mas gift. I bought _Crossing the Threshold
of Hope_ for Alan and have a thumbdrive of music for Robyn.
So this is to make a source listing and not much else. I'll do that
after the sig so you won't have to read it unless you want to.
What follows is the readdir() I understand best and then working code
from unleashed that has a 2-d resizable array.
Jens Thoerring has given me the best design idea that I have right now,
but if you think you have a better one given the source below, then I'm
all ears.
Thanks for your constructive comment and cheers,
--
frank
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#define PATH_SIZE 300
unsigned
process_directory (char *theDir)
{
DIR *dir = NULL;
struct dirent entry;
struct dirent *entryPtr = NULL;
int retval = 0;
unsigned count = 0;
char pathName[PATH_SIZE + 1];
/* Open the given directory, if we can. */
dir = opendir (theDir);
if (dir == NULL)
{
printf ("Error opening %s: %s", theDir, strerror (errno));
return 0;
}
retval = readdir_r (dir, &entry, &entryPtr);
while (entryPtr != NULL)
{
struct stat entryInfo;
if ((strncmp (entry.d_name, ".", PATH_SIZE) == 0) ||
(strncmp (entry.d_name, "..", PATH_SIZE) == 0))
{
/* Short-circuit the . and .. entries. */
retval = readdir_r (dir, &entry, &entryPtr);
continue;
}
(void) strncpy (pathName, theDir, PATH_SIZE);
(void) strncat (pathName, "/", PATH_SIZE);
(void) strncat (pathName, entry.d_name, PATH_SIZE);
if (lstat (pathName, &entryInfo) == 0)
{
/* stat() succeeded, let's party */
count++;
if (S_ISDIR (entryInfo.st_mode))
{ /* directory */
printf ("processing %s/\n", pathName);
count += process_directory (pathName);
}
else if (S_ISREG (entryInfo.st_mode))
{ /* regular file */
printf ("\t%s has %lld bytes\n",
pathName, (long long) entryInfo.st_size);
}
else if (S_ISLNK (entryInfo.st_mode))
{ /* symbolic link */
char targetName[PATH_SIZE + 1];
if (readlink (pathName, targetName, PATH_SIZE) != -1)
{
printf ("\t%s -> %s\n", pathName, targetName);
}
else
{
printf ("\t%s -> (invalid symbolic link!)\n", pathName);
}
}
}
else
{
printf ("Error statting %s: %s\n", pathName, strerror (errno));
}
retval = readdir_r (dir, &entry, &entryPtr);
}
/* Close the directory and return the number of entries. */
(void) closedir (dir);
return count;
}
int
main (void)
{
process_directory ("/etc/");
return EXIT_SUCCESS;
}
// gcc -D_GNU_SOURCE -Wall -Wextra rd3.c -o out
end rd3.c. strarr2.h:
// strarr2.h - header for string array demo
#ifndef STRARR_H__
#define STRARR_H__
void FreeStrArray(char **, size_t );
char **AllocStrArray(size_t , size_t);
int ResizeOneString(char **,
size_t ,
size_t );
int AddFilesToStrArray(char ***,
size_t ,
int ,
size_t );
int ConsolidateStrArray(char **,
size_t );
#endif
end strarr2.h begin strarr2.c:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "strarr2.h"
void FreeStrArray(char **Array, size_t NumFiles)
{
size_t index;
if(Array != NULL)
{
for(index = 0; index < NumFiles; index++)
{
if(Array[index] != NULL)
{
free(Array[index]);
}
}
free(Array);
}
}
char **AllocStrArray(size_t NumFiles, size_t Width)
{
char **Array = NULL;
size_t index;
int Success = 1;
/* allocating 0 bytes is not a great idea, and
* represents a logic error.
*/
assert(NumFiles > 0);
assert(Width > 0);
/* Just in case the zero allocation is NOT caught
* in testing, we'll check for it here.
*/
if(NumFiles > 0 && Width > 0)
{
Array = malloc(NumFiles * sizeof *Array);
if(Array != NULL)
{
for(index = 0; index < NumFiles; index++)
{
Array[index] = malloc(Width * sizeof *Array[index]);
if(NULL == Array[index])
{
Success = 0;
}
else
{
/* Making this into an empty string is a quick
* op which will almost invariably be The Right
* Thing and can never be The Wrong Thing, so
* we might as well do it.
*/
Array[index][0] = '\0';
}
}
/* If any inner allocation failed,
* we should clean up.
*/
if(1 != Success)
{
FreeStrArray(Array, NumFiles);
Array = NULL;
}
}
}
return Array;
}
int ResizeOneString(char **Array,
size_t index,
size_t NewSize)
{
char *p;
int Success = 1;
assert(Array != NULL);
p = realloc(Array[index], NewSize);
if(p != NULL)
{
Array[index] = p;
}
else
{
Success = 0;
}
return Success;
}
int AddFilesToStrArray(char ***ArrayPtr,
size_t OldNumFiles,
int NumFilesToAdd,
size_t InitWidth)
{
char **p;
int Success = 1;
int index;
int OldFiles;
OldFiles = (int)OldNumFiles;
if(NumFilesToAdd < 0)
{
for(index = OldFiles - 1;
index >= OldFiles + NumFilesToAdd;
index--)
{
free((*ArrayPtr)[index]);
}
}
p = realloc(*ArrayPtr,
(OldFiles + NumFilesToAdd) *
sizeof(**ArrayPtr));
if(p != NULL)
{
*ArrayPtr = p;
for(index = OldFiles;
Success && index < OldFiles + NumFilesToAdd;
index++)
{
(*ArrayPtr)[index] = malloc(InitWidth);
if((*ArrayPtr)[index] != NULL)
{
(*ArrayPtr)[index][0] = '\0';
}
else
{
Success = 0;
}
}
}
else
{
Success = 0;
}
return Success;
}
int ConsolidateStrArray(char **ArrayPtr,
size_t NumFiles)
{
size_t index;
size_t Len;
int NumFailures = 0;
for(index = 0; index < NumFiles; index++)
{
/* If the library has been correctly used, no
* index pointer will ever be NULL, so we should
* assert that this is the case.
*/
assert(ArrayPtr[index] != NULL);
Len = 1 + strlen(ArrayPtr[index]);
if(0 == ResizeOneString(ArrayPtr, index, Len))
{
++NumFailures;
}
}
return NumFailures;
}
/* end of strarr.c */
/*
gcc -Wall -Wextra -c -o string2.o strarr2.c */
end source listings
Technical Details
Message-ID:
<7sa7rrFg81U1@mid.individual.net>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Thread: 1200bcf240,1d887f475f1c894c,start X-Google-Attributes: gid1200bcf240,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: frank <frank@example.invalid> Newsgroups: comp.unix.programmer,gnu.gcc.help Subject: readir() II Date: Wed, 27 Jan 2010 00:21:30 -0700 Lines: 334 Message-ID: <7sa7rrFg81U1@mid.individual.net> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net Q6R9irMhSvlHpeB++kxH4wIycSWNJMDwtAHdHgqH8cX0Lhej2o Cancel-Lock: sha1:teJ4YR0sdwbn8+BBekYM1qngzdE= User-Agent: Thunderbird 2.0.0.23 (X11/20090817)