0

Does anyone know how to copy a directory, including all subdirectories across to another folder The code I've written so far copies over text files and directories, but it doesn't copy all the sub-directories. Before going any further, I have seen questions like this before, but there don't cover what I need to know, or there covered in other languages.

Sorry if my code is a mess.

Anyway, here is my code:

#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define BUFFERSIZE 4096
#define COPYMODE 0644
#define FILE_MODE S_IRWXU

DIR * directory;
struct dirent * entry;
DIR * directoryTwo;
struct dirent * entryTwo;
struct stat info;

// copyFile

void copyFile(const char * src, const char * dst)
{
    FILE * file1, *file2;
    file1 = fopen(src, "r");
    if(file1 == NULL)
    {
        perror("Cannot open source file");
        fclose(file1);
        exit(-1);
    }

    file2 = fopen(dst, "w");

    if(file2 == NULL) {
        perror("cannot open destination file");
        fclose(file2);
        exit(-1);
    }

    char currentchar;
    while((currentchar = getc(file1)) != EOF) {
        fputc(currentchar, file2);
    }

    fclose(file1);
    fclose(file2);
}

void goThoughFile(const char * srcFilePath, const char * dst)
{
    char srcFile[260];
    char dstFile[260];

    directory = opendir(srcFilePath);
    if(directory == NULL) {
        printf("Error");
        exit(1);
    }

    while((entry = readdir(directory)) != NULL)
    {
        if(strstr(entry->d_name, "DS_Store") || strstr(entry->d_name, ".localized") ||
                strstr(".", &entry->d_name[0]) || strstr("..", &entry->d_name[0]))
            continue;

        else if(entry->d_type == DT_REG)
        {
            sprintf(srcFile, "%s/%s", srcFilePath, entry->d_name);
            sprintf(dstFile, "%s/%s", dst, entry->d_name);
            copyFile(srcFile, dstFile);
        }

        if(entry->d_type == DT_DIR)
        {
            chdir(dst);
            mkdir(entry->d_name, S_IRWXU);
            sprintf(dstFile, "%s%s/%s", dst, entry->d_name, "/..");
            chdir(dstFile);
            mkdir(entry->d_name, S_IRWXU);
        }
    }
}

int main()
{
    goThoughFile(someFilePath, anotherFilePath);
    return 0;
}
Siguza
  • 21,155
  • 6
  • 52
  • 89
Joe Kur
  • 37
  • 8
  • Possible duplicate of [Recursive directory copying in C](http://stackoverflow.com/questions/15177378/recursive-directory-copying-in-c) – Gaurav Pathak Apr 16 '17 at 09:21
  • I did see that post, but how would you use that to copy the directories as you come across them? – Joe Kur Apr 16 '17 at 22:32

1 Answers1

0

What you want to achieve using struct dirent can not be guaranteed to work.

You are checking if(entry->d_type == DT_DIR) the file for type Directory, but if you read the manual of readdir(3) it clearly says in the comment of structure that it is not supported by all filesystem types.

On Linux, the dirent structure is defined as follows:

       struct dirent {
           ino_t          d_ino;       /* inode number */
           off_t          d_off;       /* not an offset; see NOTES */
           unsigned short d_reclen;    /* length of this record */
           unsigned char  d_type;      /* type of file; not supported
                                          by all filesystem types */
           char           d_name[256]; /* filename */
       };

You have to use getdents(). For more clarification please refer this post.

Community
  • 1
  • 1
Gaurav Pathak
  • 1,065
  • 11
  • 28