Thread: traversing directories using fork()

  1. #1
    Registered User
    Join Date
    Mar 2014
    Posts
    95

    traversing directories using fork()

    I try to go in folders and read files using fork(). I use file tree walk function to go in the folders recursively. The basic idea is that there will be children number of files and directory in a directory. The children read each file seperately and concurrently. But, if there are directories the children will be parents of the children to read files. I've tried to explain below scheme
    traversing directories using fork()-5bgyh-png
    Code:
    static int soner_each_time(const char *filepath, const struct stat *info,
                            int typeflag, struct FTW *ftwinfo)
        {
            
            pid_t   pid = 0;
            char    buf[BUFSIZE];
            int     status;
            int     i = 0;
            
            /* The variables are related to functions of reading file  */
        
            int     totalLines;
            char    arr[TOTALNUMBEROFLINES][BUFSIZE];
            int     retval;
            
        
            const char *const filename = filepath + ftwinfo->base;
            
            if (( pid = fork()) < 0) {
                const int cause = errno;
                fprintf(stderr, "Fork error: %s\n", strerror(cause));
                errno = cause;
                return -1;
            }
            else if( pid > 0 ) // parent
            {
                if (typeflag == FTW_DP || typeflag == FTW_D)
                {
                    sprintf(buf, "%*s%s\n\n", ftwinfo->level * 4, "", filepath);
                    write(1, buf, strlen(buf));
                    pid = wait(&status);
                    if (pid == -1)
                        perror("Failed to wait for child");
                    else if (WIFEXITED(status) && !WEXITSTATUS(status))
                        printf("parent [%d] reaped child [%d]\n", getpid(), pid);
                    else if (WIFEXITED(status))
                        printf("Child %ld terminated with return status %d\n",
                               (long)pid, WEXITSTATUS(status));
                    else if (WIFSIGNALED(status))
                        printf("Child %ld terminated due to uncaught signal %d\n",
                               (long)pid, WTERMSIG(status));
                    else if (WIFSTOPPED(status))
                        printf("Child %ld stopped due to signal %d\n",
                               (long)pid, WSTOPSIG(status));
                }
            }
            
            
            if (pid == 0) // child
            {
                if (typeflag == FTW_F)
                {
                    sprintf(buf, "||| Child [%d] of parent [%d]: %s |||\n", getpid(), getppid(), filename);
                    write(1, buf, strlen(buf));
                    
                    /* Both of them are about reading function */
                    totalLines = storeLinesInArray(filename, arr);
                    
                    retval = for_each_file(filename, totalLines, key, arr);
                    
                    sprintf(buf, "||| Child [%d] of parent [%d] is about to exit |||\n", getpid(), getppid());
                    write(1, buf, strlen(buf));
                }
                
                else if (typeflag == FTW_DP || typeflag == FTW_D)
                {
                    sprintf(buf, "%*s%s\n\n", ftwinfo->level * 4, "", filepath);
                    write(1, buf, strlen(buf));
                }
                
            }
                return 0;
        }

    FTW_DP and FTW_D indicates folders FTW_F indicates files. Basically, I tried in the code fork() every time. If it is parent, It waits for its children read the files. Because the function is recursive, it will fork every calling. But, there's something about it I cant't get it forks more than one for one file. For example there should be one child for 1a.txt but for this scheme it is 8. Forking subject is really difficult. I do everyday exercises and try to understand it. Your explanations and helps will improve my skill in that branch.
    Last edited by Ph0x; 03-15-2016 at 02:42 PM.

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    As you should already know after 92 posts, you need to post a program we can compile and run, not just a random chunk of code that may or may not contain the error. Neither the call to ftw or the recursive call to your own routine is in the code you posted. Think of it this way, if you can't find the problem then it could be ANYWHERE in the code. Create the smallest program you can that demonstrates the problem. E.g, remove the storeLinesInArray calls, for instance; just print to the screen.

  3. #3
    Registered User
    Join Date
    Mar 2014
    Posts
    95
    Quote Originally Posted by algorism View Post
    As you should already know after 92 posts, you need to post a program we can compile and run, not just a random chunk of code that may or may not contain the error. Neither the call to ftw or the recursive call to your own routine is in the code you posted. Think of it this way, if you can't find the problem then it could be ANYWHERE in the code. Create the smallest program you can that demonstrates the problem. E.g, remove the storeLinesInArray calls, for instance; just print to the screen.
    Code:
    #define _POSIX_C_SOURCE 200809L
    #define _XOPEN_SOURCE 700
    #include <unistd.h>
    #include <dirent.h>
    #include <stdlib.h>
    #include <locale.h>
    #include <string.h>
    #include <ftw.h>
    #include <stdio.h>
    
    
    #define TOTALNUMBEROFLINES 1000
    #define BUFSIZE 1000
    
    
    
    
    void err_sys(const char *const str)
    {
        perror(str);
        fflush(stdout);
        exit(1);
    }
    
    
    int storeLinesInArray(const char *file, char lines[][BUFSIZE])
    {
        return 0;
    }
    
    
    static int for_each_file(const char *filepath, int totalLines, const char *key, const char arr[][BUFSIZE])
    {
        
        fprintf(stdout, "File name is = %s\n", filepath);
        fflush(stdout);
    
    
        
        return 0;
    }
    
    
    static int soner_each_time(const char *filepath, const struct stat *info,
                               int typeflag, struct FTW *ftwinfo)
    {
        
        pid_t   pid = 0;
        char    buf[BUFSIZE];
        int     status;
        
        /* The variables are related to functions of reading file  */
        
        int     totalLines;
        char    arr[TOTALNUMBEROFLINES][BUFSIZE];
        int     retval;
        
        
        const char *const filename = filepath + ftwinfo->base;
        
        if (( pid = fork()) < 0) {
            perror("failed fork");
            exit(-1);
        }
        else if( pid > 0 ) // parent
        {
            if (typeflag == FTW_DP || typeflag == FTW_D)
            {
                sprintf(buf, "%*s%s\n\n", ftwinfo->level * 4, "", filepath);
                write(1, buf, strlen(buf));
                pid = wait(&status);
                if (pid == -1)
                    perror("Failed to wait for child");
                else if (WIFEXITED(status) && !WEXITSTATUS(status))
                    printf("parent [%d] reaped child [%d]\n", getpid(), pid);
                else if (WIFEXITED(status))
                    printf("Child %ld terminated with return status %d\n",
                           (long)pid, WEXITSTATUS(status));
                else if (WIFSIGNALED(status))
                    printf("Child %ld terminated due to uncaught signal %d\n",
                           (long)pid, WTERMSIG(status));
                else if (WIFSTOPPED(status))
                    printf("Child %ld stopped due to signal %d\n",
                           (long)pid, WSTOPSIG(status));
            }
        }
        
        
        if (pid == 0) // child
        {
            if (typeflag == FTW_F)
            {
                sprintf(buf, "||| Child [%d] of parent [%d]: %s |||\n", getpid(), getppid(), filename);
                write(1, buf, strlen(buf));
                
                /* Both of them are about reading function */
                totalLines = storeLinesInArray(filename, arr);
                
                retval = for_each_file(filename, totalLines, "not needed now", arr);
                
                sprintf(buf, "||| Child [%d] of parent [%d] is about to exit |||\n", getpid(), getppid());
                write(1, buf, strlen(buf));
            }
            
            else if (typeflag == FTW_DP || typeflag == FTW_D)
            {
                sprintf(buf, "%*s%s\n\n", ftwinfo->level * 4, "", filepath);
                write(1, buf, strlen(buf));
            }
            
        }
        return 0;
    }
    
    
    
    
    
    
    int main(int argc, char *argv[])
    {
        
        if (nftw("here is directory path", soner_each_time, 15, FTW_CHDIR)) {
            exit(-1);
        }
        
        return 0;
    }

  4. #4
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Now I see the structure of your program.

    The fork call duplicates the entire program, which then continues on it's merry way, including the ntfw function, the call to which has also been duplicated. No wonder you're getting multiple copies of the filenames passed to your function!

    If you can describe in general terms what exactly you're trying to accomplish, there's gotta be a better way.
    Actually, simply exiting the child at the end of it's code block might be enough.

    EDIT: Or maybe the child should return FTW_STOP from soner_each_time.
    Last edited by algorism; 03-15-2016 at 04:17 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 02-27-2014, 03:53 AM
  2. Traversing directories using the NtQueryDirectoryFile()
    By rohan_ak1 in forum Windows Programming
    Replies: 1
    Last Post: 10-08-2009, 07:01 AM
  3. build tree of directories sub-directories using linked-lists
    By geekoftheweek in forum C Programming
    Replies: 3
    Last Post: 10-02-2008, 11:13 PM
  4. Traversing trees
    By jamesedwards in forum C Programming
    Replies: 3
    Last Post: 12-03-2005, 03:32 PM
  5. Traversing Directories
    By C Minor in forum C Programming
    Replies: 4
    Last Post: 06-16-2002, 11:28 PM