1

I'm currently working on a problem that is a C program to allow me to keep directories in sync. The jist of it is:

  1. If a file is in Directory A and not in Directory B, copy the file to Directory B.
  2. If the file is in both Directory A and Directory B, copy the newest version of the file to the Directory with the oldest.
  3. If a file is in Directory B but not Directory A, delete the file.

I was having issues getting the full path of the files I need to open and delete. So I decided to use the C function chdir(path).

I am able to create a new file and remove the files, but for some reason, the data in the file is not copied even after opening two file streams to do so and I'm not sure why. The code is definitely messy, but I can't figure out where I'm going wrong. Insight would be appreciated. I am new to C and dealing with buffers and memory management is something I'm not quite good at just yet. Any ideas?

#include "csapp.h"
#include <stdio.h>
#include <dirent.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

// prototypes
bool inOtherDir(char*, char*);
void copyFile(char*, char*, char*, char*);
int isNewer(char*, char*, char*, char*);

int main(int argc, char **argv ) {

    // variables
    struct dirent *dirone;
    struct dirent *dirtwo;
    char* dirAPath = argv[1]; // this will be used for absolute paths
    char* dirBPath = argv[2];
    char cwd[256];
    char* cwdptr = cwd;

    // get the CWD for use later
    if(getcwd(cwd, sizeof(cwd)) == NULL) {
        perror("getcwd() error()");
        return 1;
    }

    // Testing
    // printf("CWD is: %s\n", cwd);

    if (argc < 3) {
        printf("Not enough arguments provided, please provide two directories.\n");
        return 1;
    }

    // open directory a
    DIR *ptrone = opendir(argv[1]);
    // open directory b
    DIR *ptrtwo = opendir(argv[2]);

    if (ptrone == NULL || ptrtwo == NULL) {
        printf("Could not open directory\n");
        return 1;
    }

    printf("Checking Sync Status: \n");
    // Open the directory and check to see if the file is a regular file
    // if it is regular, then do work on it based on if its in the other
    // directory or not.
    while ((dirone = readdir(ptrone)) != NULL) {
        if (dirone->d_type == DT_REG) {
            if(inOtherDir(dirone->d_name, argv[2])) {
                printf("File %s is in both directories.\n", dirone->d_name);
            } else {
                printf("File %s is in Directory A but not Directory B.\n", dirone->d_name);
                printf("Copying %s in Directory A to Directory B.\n",dirone->d_name);
                copyFile(dirone->d_name,dirAPath, dirBPath,cwdptr);
            }
        }
    }

    // check for files only in directory B, then delete them
    while ((dirtwo = readdir(ptrtwo)) != NULL) {
        if (dirtwo->d_type == DT_REG) {
            if(inOtherDir(dirtwo->d_name, argv[1])) {
                printf("File %s is in both directories.\n", dirtwo->d_name);
            } else {
                printf("File %s will be removed from the directory.\n",dirtwo->d_name);
                chdir(dirBPath);    
                remove(dirtwo->d_name);
                chdir(cwd);
            }
        }
    }
    closedir(ptrone);
    closedir(ptrtwo);
    return 0;
}

// Look through the directory to see if the same file is in there returns
// true if the file is in that directory and returns false if not.
bool inOtherDir(char* filename, char* direct)  {

    struct dirent *buf;
    DIR *directory = opendir(direct);

    if(directory == NULL) {
        printf("Could not open directory.");
        exit(1);
    }

    while((buf = readdir(directory)) != NULL) {
        if ((strcmp(filename, buf->d_name)) == 0) {
            return true;
        }
    }
    closedir(directory);
    return false;

}

// Copies the file from one directory to the other
void copyFile(char* filename, char* directory_from,char* directory_to, char* cwd) {

    FILE *file, *copyfile;
    char c;

    chdir(directory_from);
    file = fopen(filename,"r");
    if(file == NULL) {
        printf("Cannot open the file %s in copyFile.\n", filename);
    }
    chdir(cwd);
    chdir(directory_to);
    copyfile = fopen(filename, "w+");
    if(copyfile == NULL) {
        printf("Cannot open copy of the file %s in copyFile.\n", filename);
    }

    c = fgetc(file);
    while(c != EOF){
        fputc(c, copyfile);
        c = fgetc(file);
    }

    printf("Contents copied successfully.\n");

    fclose(file);
    fclose(copyfile);
    chdir(cwd);
    return;

}
M Dey
  • 75
  • 1
  • 1
  • 7
  • 1
    Your code looks correct from a very quick inspection. But you could try using a tool like [valgrind](http://valgrind.org) to check if you used some uninitialized value or made an attempt to mess with memory that doesn't belong to your program's heap. BTW, this is a fun homework. Also, why don't you test everything in the same place. HINT: write a function that given a file does what it has to do instead of embedding/inlining the code in the while loop. – Iharob Al Asimi Feb 21 '18 at 21:08
  • Iharob, I will look into running this with Valgrind. Not sure what you meant about testing it in another function instead of the while loop. Are you saying just test one file and not the entire directory? Those print statements are required by the assignment description for logging. If you meant what I was suggesting you did, good idea. I will take that into account and test that way as well. – M Dey Feb 21 '18 at 21:13
  • No, I mean isolate the code that performs the work on a single file. So that you can make it more readable and understandable and easily spot any bugs, somethin like `handle_file(const char *const dirname, const char *const filepath) { if (is_in_other_dir(dirname, filepath) == true) ... }` – Iharob Al Asimi Feb 21 '18 at 21:15
  • Ah, understood. I will do that. Thanks! – M Dey Feb 21 '18 at 21:19

0 Answers0