Thread: Directory Listing

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    36

    Directory Listing

    I wrote this test program to familiarize myself with accessing file information but I keep getting a couple of errors I can't figure out. Please help.

    Code:
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    
    int main(int argc, char *argv[])
    {
        void printfiles(char *);
    
        DIR *d = opendir(*++argv);
    
        if (argc == 1 || argc > 2)
        {
            fprintf(stderr, "error: must have ONE file name\n");
            return 0;
        }
        printfiles(d->d.name);
        closedir(d);
        return 0;
    }    
    
    #include <string.h>
    
    void printfiles(char *diren)
    {
        int is_searchable(char *);
        void dirwalk(char *);
    
        struct stat finfo;
    
        stat(diren, &finfo);
        if ((finfo.st_mode & S_IFMT) == S_IFDIR)
            dirwalk(diren);
        if (strcmp(diren, ".") != 0 && strcmp(diren, "..") != 0)
        {
            if (is_searchable(diren))
                printf("%s\t%s\n", diren, "*marked for search*");
            else
                printf("%s\n", diren);
        }
    }
        
    void dirwalk(char *dname)
    {
        DIR *d = opendir(dname);
        struct dirent *file;
    
        while ((file = readdir(d)) != NULL)
            printfiles(file->name);
    
        closedir(d);
    }
    
    int is_searchable(char *fname)
    {
        while (*fname != '\0')
            ++fname;
    
        fname -= 2;
        if (strcmp(fname, ".c") == 0 || strcmp(fname, ".h") == 0)
            return 1;
        else
            return 0;
    }
    [T3256@GURY Text.File.Keyword.Search]$ cc program.search.c -o search
    program.search.c: In function ‘main’:
    program.search.c:17: error: dereferencing pointer to incomplete type
    program.search.c: In function ‘dirwalk’:
    program.search.c:49: error: ‘struct dirent’ has no member named ‘name’

  2. #2
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by rrc55 View Post
    I wrote this test program to familiarize myself with accessing file information but I keep getting a couple of errors I can't figure out. Please help.

    Code:
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    
    int main(int argc, char *argv[])
    {
        void printfiles(char *);
    
        DIR *d = opendir(*++argv);
    
        if (argc == 1 || argc > 2)
        {
            fprintf(stderr, "error: must have ONE file name\n");
            return 0;
        }
        printfiles(d->d.name);
        closedir(d);
        return 0;
    }    
    
    #include <string.h>
    
    void printfiles(char *diren)
    {
        int is_searchable(char *);
        void dirwalk(char *);
    
        struct stat finfo;
    
        stat(diren, &finfo);
        if ((finfo.st_mode & S_IFMT) == S_IFDIR)
            dirwalk(diren);
        if (strcmp(diren, ".") != 0 && strcmp(diren, "..") != 0)
        {
            if (is_searchable(diren))
                printf("%s\t%s\n", diren, "*marked for search*");
            else
                printf("%s\n", diren);
        }
    }
        
    void dirwalk(char *dname)
    {
        DIR *d = opendir(dname);
        struct dirent *file;
    
        while ((file = readdir(d)) != NULL)
            printfiles(file->name);
    
        closedir(d);
    }
    
    int is_searchable(char *fname)
    {
        while (*fname != '\0')
            ++fname;
    
        fname -= 2;
        if (strcmp(fname, ".c") == 0 || strcmp(fname, ".h") == 0)
            return 1;
        else
            return 0;
    }
    Well there is a lot that is kinda strange about this but name is d_name[]....just saying...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  3. #3
    Registered User
    Join Date
    Feb 2009
    Posts
    36
    Quote Originally Posted by jeffcobb View Post
    Well there is a lot that is kinda strange about this but name is d_name[]....just saying...
    Thanks that did the trick for dirent. As for DIR, I guess you can't access its members directly? No matter, I just changed a few things and used readdir instead.

    From wikipedia:
    DIR - A structure representing a directory stream. Its structure is not defined by POSIX, and is usually opaque to users.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is old-school for DOS, but it still works in Windows XP

    Code:
    /* findnext example */
    
    #include <stdio.h>
    #include <dir.h>
    
    int main(void)
    {
       struct ffblk ffblk;
       int done;
       printf("Directory listing of *.*\n");
       done = findfirst("*.*",&ffblk,0);
       while (!done)
       {
          printf("  %s\n", ffblk.ff_name);
          done = findnext(&ffblk);
       }
       done = getchar();
       return 0;
    }

  5. #5
    Registered User
    Join Date
    Feb 2009
    Posts
    36
    I've expanded my program to do a few more things . I'm a total noob and I'm just messing around with this in hopes of learning some things so please don't make too much fun of me. Anyway, I've been messing with this all day and I can't think straight any more. I keep getting a segfault and was hoping you guys could help me.

    My program:
    Code:
    /* GibletSearch v1.1 */
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define MAXLINE 1000
    #define MAXWORD 100
    
    char keyword[MAXWORD+2];
    float file_total, files_left;
    
    typedef struct
    {
    	int o;		/* number of occurences */
    	char *fn;	/* file name */
    } Result;
    
    Result *result_tab = NULL;
    /* searches source files for keyword and prints containing files */
    int main(int argc, char *argv[])
    {
    	void build_result(char *);
    	int get_num_files(char *);
    
    	int e;
    	Result *rp;
    
    	if (argc == 1 || argc > 2)
    	{
    		fprintf(stderr, "Usage: ./search [dir] [keyword]\n");
    		return 0;
    	}
    	printf("**************************************\n");
    	printf("GibletSearch v1.1\n");
    	printf("**************************************\n\n");
    	printf("                     by Assimilator :D\n");
    	printf("--------------------------------------\n");
    	file_total = files_left = get_num_files(*++argv);
    	++files_left;
    	printf("Enter keyword: ");
    	fgets(keyword, MAXWORD+1, stdin);
    	printf("\nLooking in: %s\n", *argv);
    	printf("[--------------------------------------------------] %3i%%", 0);
    
    	for (e = 0; keyword[e] != '\n'; ++e)
    		;
    
    	keyword[e] = '\0';
    	build_result(*argv);
    	printf("\n\n");
    	printf("================Results===============\n\n");
    
    	for (rp = result_tab; rp->fn != NULL; ++rp)
    		printf("%s (%i)\n", rp->fn, rp->o);
    
    	free(result_tab);
    	printf("--------------------------------------\n");
    	printf("*(n) = number ot times found in file");
    	printf("\n\nGoodbye! :D\n");
    	return 0;
    }	
    /* buils the result table */
    void build_result(char *diren)
    {
    	int is_searchable(char *);
    	void dirwalk(char *);
    	int searchkey(char *);
    	void result_alloc(char *, int);
    	void updt_prg(void);
    
    	struct stat finfo;
    	int count;
    
    	if (stat(diren, &finfo) == -1)
    		fprintf(stderr, "stats error: %s\n", diren);
    	if ((finfo.st_mode & S_IFMT) == S_IFDIR)
    		dirwalk(diren);
    	if (is_searchable(diren))
    		if (count = searchkey(diren))
    			result_alloc(diren, count);
    	--files_left;
    	updt_prg();
    	
    }
    /* goes through files in directories recursively */
    void dirwalk(char *dname)
    {
    	void build_result(char *);
    
    	struct dirent *file;
    	char newdiren[FILENAME_MAX+1];
    
    	DIR *d = opendir(dname);
    
    	while ((file = readdir(d)) != NULL)
    	{
    		if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
    			continue;
    		if (strlen(dname) + strlen(file->d_name) + 1 <= FILENAME_MAX)
    		{
    			if ((sprintf(newdiren, "%s/%s", dname, file->d_name)) < 0)
    			{
    				fprintf(stderr, "error copying new path\n");
    				--files_left;
    				continue;
    			}
    		}
    		else
    		{
    			fprintf(stderr, "file name length error: %s/%s\n", dname, file->d_name);
    			continue;
    		}
    		build_result(newdiren);
    	}
    
    	closedir(d);
    }
    /* marks files for search */
    int is_searchable(char *fname)
    {
    	while (*fname != '\0')
    		++fname;
    
    	fname -= 2;
    	if (strcmp(fname, ".c") == 0 || strcmp(fname, ".h") == 0)
    		return 1;
    	else
    		return 0;
    }
    /* searches files for keyword */
    int searchkey(char *fname)
    {
    	int getline(FILE *, char *);
    	char line[MAXLINE+1];
    
    	FILE *fp = fopen(fname, "r");
    	int c;
    	char *chp;
    
    	int cnt = 0;
    
    	if (fp == NULL)
    	{
    		fprintf(stderr, "Error opening file '%s'\n", fname);
    		return 0;
    	}
    
    	while ((c = getline(fp, line)) != EOF)
    	{
    		for (chp = line; (chp = strstr(chp, keyword)) != NULL; chp += strlen(keyword))
    			++cnt;
    			
    		if (c < 0)
    			fprintf(stderr, "Error: Maximum line length exceeded '%s' in file '%s'\n", line, fname);
    	}
    
    	if (c == EOF)
    		for (chp = line; (chp = strstr(chp, keyword)) != NULL; chp += strlen(keyword))
    			++cnt;
    
    	fclose(fp);
    	if (cnt)
    		return cnt;
    	else
    		return 0;
    }
    /* gets the next line of input from file */
    int getline(FILE *f, char *s)
    {
    	int c;
    
    	int cnt = 0;
    
    	while ((c = fgetc(f)) != EOF && c != '\n')
    		if (cnt <= MAXLINE)
    			*s++ = c;
    		else
    		{
    			*--s = '\0';
    			return -1;
    		}
    
    	*s = '\0';
    	return c;
    }
    /* dynamically allocates the result table */
    void result_alloc(char *name, int occur)
    {
    	Result entry;
    	Result *rp;
    
    	static int no_entries = 1;
    
    	result_tab = (Result *) realloc(result_tab, sizeof entry * ++no_entries);
    	rp = result_tab;
    	entry.fn = (char *) malloc(strlen(name) + 1);
    	strcpy(entry.fn, name);
    	entry.o = occur;
    	rp += no_entries - 2;
    	*rp++ = entry;
    	rp->fn = NULL;
    }
    /* counts the number of files in the directory */
    int get_num_files(char *name)
    {
    	char newname[FILENAME_MAX+1];
    	struct stat fino;
    	struct dirent *f;
    
    	int fcount = 0;
    	DIR	*dp = opendir(name);
    
    	while ((f = readdir(dp)) != NULL)
    	{
    		if (strcmp(f->d_name, ".") != 0 && strcmp(f->d_name, "..") != 0)
    			++fcount;
    		if (sizeof(name) + sizeof(f->d_name) <= FILENAME_MAX)
    		{
    			if ((sprintf(newname, "%s/%s", name, f->d_name)) < 0)
    			{
    				fprintf(stderr, "file count error: error copying new path\n");
    				continue;
    			}
    		}
    		else
    		{
    			fprintf(stderr, "file count error: a file has exceeded max name length\n");
    			continue;
    		}
    		stat(newname, &fino);
    		if ((fino.st_mode & S_IFMT) == S_IFDIR && strcmp(f->d_name, ".")
    		!= 0 && strcmp(f->d_name, "..") != 0                           )
    			fcount += get_num_files(newname);
    	}
    
    	closedir(dp);
    	return fcount;
    }
    
    #define PROGRESSLEN 57
    #define BARLENGTH 50
    /* prints a pretty progress bar */
    void updt_prg(void)
    {
    	int x, pnds, prcnt;
    
    	for (x = PROGRESSLEN; x > 0; --x)
    		putchar('\b');
    
    	prcnt = (file_total - files_left) / file_total * 100;
    	pnds = prcnt * BARLENGTH / 100;
    
    	putchar('[');
    
    	for (x = 0; x < pnds; ++x)
    		putchar('#');
    
    	for (x = 0; x < BARLENGTH - pnds; ++x)
    		putchar('-');
    
    	printf("] %3i%%", prcnt);
    	return;
    }
    Output:
    [T3256@GURY GibletSearch]$ ./gibletsearch '/home/T3256/Tools/eggdrop/eggdrop1.6.19'
    **************************************
    GibletSearch v1.1
    **************************************

    by Assimilator
    --------------------------------------
    Enter keyword: global_funcs

    Looking in: /home/T3256/Tools/eggdrop/eggdrop1.6.19
    [##################################################] 100%

    ================Results===============

    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/server.mod/server.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/notes.mod/notes.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/dns.mod/dns.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/transfer.mod/transfer.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/wire.mod/wire.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/console.mod/console.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/compress.mod/compress.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/blowfish.mod/blowfish.c (4)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/irc.mod/irc.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/uptime.mod/uptime.c (3)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/assoc.mod/assoc.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/share.mod/share.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/channels.mod/channels.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/filesys.mod/filesys.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/woobie.mod/woobie.c (2)
    /home/T3256/Tools/eggdrop/eggdrop1.6.19/src/mod/ctcp.mod/ctcp.c (2)
    --------------------------------------
    *(n) = number ot times found in file

    Goodbye!
    [T3256@GURY GibletSearch]$
    This directory works just fine but this next one breaks it.

    GDB:
    (gdb) run '/home/T3256/Tools/valgrind-3.5.0'
    Starting program: /home/T3256/C-Programs/Random/GibletSearch/gibletsearch '/home/T3256/Tools/valgrind-3.5.0'
    **************************************
    GibletSearch v1.1
    **************************************

    by Assimilator
    --------------------------------------
    Enter keyword: a

    Looking in: /home/T3256/Tools/valgrind-3.5.0
    [######################################------------] 76%
    Program received signal SIGSEGV, Segmentation fault.
    _IO_getc (fp=0x73623e2d) at getc.c:40
    40 _IO_acquire_lock (fp);
    (gdb) where
    #0 _IO_getc (fp=0x73623e2d) at getc.c:40
    #1 0x08048de0 in getline (f=0x73623e2d,
    s=0xbfffce0f " { if (groupPos == 0) { groupNo++; if (groupNo >= nSelectors) { retVal = (-4); goto save_state_and_return; };; groupPos = 50; gSel = s->selector[groupNo]; gMinlen = s->minLens[gSel]; gLimit = &(s"...) at gibletsearch.c:178
    #2 0x08048d1f in searchkey (fname=0x6b616572 <Address 0x6b616572 out of bounds>) at gibletsearch.c:152
    Valgrind:
    [T3256@GURY GibletSearch]$ valgrind ~/C-Programs/Random/GibletSearch/gibletsearch '/home/T3256/Tools/valgrind-3.5.0'
    ==3428== Memcheck, a memory error detector
    ==3428== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
    ==3428== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
    ==3428== Command: /home/T3256/C-Programs/Random/GibletSearch/gibletsearch /home/T3256/Tools/valgrind-3.5.0
    ==3428==
    **************************************
    GibletSearch v1.1
    **************************************

    by Assimilator
    --------------------------------------
    Enter keyword: e

    Looking in: /home/T3256/Tools/valgrind-3.5.0
    [###################==3428== Invalid read of size 2] 76%
    ==3428== at 0xA064CD: getc (getc.c:40)
    ==3428== by 0x8048DDF: getline (gibletsearch.c:178)
    ==3428== by 0x8048D1E: searchkey (gibletsearch.c:152)
    ==3428== by 0x62203B75: ???
    ==3428== Address 0x73623e2d is not stack'd, malloc'd or (recently) free'd
    ==3428==
    ==3428==
    ==3428== Process terminating with default action of signal 11 (SIGSEGV)
    ==3428== Access not within mapped region at address 0x73623E2D
    ==3428== at 0xA064CD: getc (getc.c:40)
    ==3428== by 0x8048DDF: getline (gibletsearch.c:178)
    ==3428== by 0x8048D1E: searchkey (gibletsearch.c:152)
    ==3428== by 0x62203B75: ???
    ==3428== If you believe this happened as a result of a stack
    ==3428== overflow in your program's main thread (unlikely but
    ==3428== possible), you can try to increase the size of the
    ==3428== main thread stack using the --main-stacksize= flag.
    ==3428== The main thread stack size used in this run was 10485760.
    [######################################------------] 76%==3428==
    ==3428== HEAP SUMMARY:
    ==3428== in use at exit: 55,371 bytes in 689 blocks
    ==3428== total heap usage: 2,270 allocs, 1,581 frees, 3,049,563 bytes allocated
    ==3428==
    ==3428== LEAK SUMMARY:
    ==3428== definitely lost: 0 bytes in 0 blocks
    ==3428== indirectly lost: 0 bytes in 0 blocks
    ==3428== possibly lost: 0 bytes in 0 blocks
    ==3428== still reachable: 55,371 bytes in 689 blocks
    ==3428== suppressed: 0 bytes in 0 blocks
    ==3428== Rerun with --leak-check=full to see details of leaked memory
    ==3428==
    ==3428== For counts of detected and suppressed errors, rerun with: -v
    ==3428== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 8)
    Segmentation fault
    Thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. On reading Directory contents and listing them.
    By Deathfrost in forum C Programming
    Replies: 9
    Last Post: 07-14-2009, 08:21 AM
  2. Couple errors please help :-D
    By JJJIrish05 in forum C Programming
    Replies: 9
    Last Post: 03-06-2008, 02:54 AM
  3. Listing specific files in a directory
    By knirirr in forum C Programming
    Replies: 14
    Last Post: 01-29-2008, 05:42 AM
  4. Replies: 4
    Last Post: 06-05-2006, 03:24 AM
  5. recursive directory listing help
    By laney69er in forum C Programming
    Replies: 2
    Last Post: 03-13-2006, 01:07 PM