Thread: suggestions for my file backup app (for linux)

  1. #1
    Prying open my third eye.
    Join Date
    Jun 2005
    Posts
    45

    suggestions for my file backup app (for linux)

    I just got to working code with my first program dealing with the unix file system. all it does is accept a command line path to a directory, and a path to the directory where the files will be copied. it then copies all the files and folders to the new folder. so if you wanted to backup the folder "/home/user/files" into "/home/user/old" you would use:

    ./backup /home/user/files /home/user/files/old

    and the program will copy the content os "files" to a new folder "old~BACKUP".

    I would just like some people to look it over and make some suggestions as to what it good/bad because I know better than anyone that it could use improvement.

    thanks, and here is the code

    EDIT: I know that some parts of the code are rather cryptic, such as when multiple calls to strcat, i am aware of this but this is the only way i thought of doing (at first).

    EDIT #2: Ahhh, posted too quick. I already found a problem, when trying to backup a folder within a folder, my calls to create another instance of backup (would that be considered recursive if i used the system() call?) fail because there is no path to the backup executable in the other folders. I think I could get around it by editing path files on my machine but how could I get it to work in a portable way?

    EDIT #3: Last one i swear! I can run the program fine if the executable is in the /usr/bin directory, which is in most peoples PATHs, so is that the best way to use the program? Or is there another way to get around this so that the program can be run from anywhere?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #define SIZE  75
    
    struct dir_path
    {
      char *orig;
      char *new;
    };
    
    char *create_dir(char *orig, char *new);
    char *backup(char *filepath, char *dirpath, char *name);
    
    int main(int argc, char *argv[])
    {
      char new[SIZE], *orig, *temp;
      DIR *directory = NULL;
      struct dirent *entry;
      struct dir_path *dir = malloc(sizeof(struct dir_path));
    
      orig = malloc(SIZE);
      temp = malloc(SIZE);
    
      memset(new, '\0', SIZE);
      memset(temp, '\0', SIZE);
      memset(orig, '\0', SIZE);
    
      if (argc != 3) {
        printf("USAGE: ./backup <source dir> <dest dir>\n");
        exit(EXIT_FAILURE);
      }
      dir->orig = argv[1];
      dir->new = argv[2];
    
      if ((directory = opendir(dir->orig)) == NULL) {
        perror("opendir");
        exit(EXIT_FAILURE);
      }
    
      dir->new = create_dir(argv[1], argv[2]);
      sprintf(new, "%s", dir->new);
      sprintf(orig, "%s", dir->orig);
      sprintf(temp, "%s", dir->orig);
    
      while (errno = 0, (entry = readdir(directory)) != NULL) {
        if ((strcmp(entry->d_name,".") == 0) || (strcmp(entry->d_name,"..") == 0))
          continue;
    
        /* concatenates path string */
        strcat(temp, "/");
        strcat(temp, entry->d_name);
    
        /* calls backup function to copy directory files */
        backup(temp, new, entry->d_name);
        memset(temp, '\0', SIZE);
        sprintf(temp, "%s", dir->orig);
      }
    
      closedir(directory);
      free(dir);
      return 0;
    }
    
    /* creates a directory in the parent directory of PATH */
    /* directory name is <PATH>~BACKUP */
    char *create_dir(char *orig, char *newdir)
    {
      char *path = malloc(SIZE),
           *new = malloc(SIZE);
    
      sprintf(path, "%s", orig);
      sprintf(new, "%s", newdir);
    
      chdir(newdir);
    
      new = strcat(new, "~BACKUP");
      if (mkdir(new, 0755) == -1) {
        perror("mkdir");
        exit(EXIT_FAILURE);
      }
      chdir(orig);
    
      return new;
    }
    
    char *backup(char *filepath, char *newdir, char *name)
    {
      int fd, newfile, b_read, b_written, i, k=0;
      char buf[4096], *temp = malloc(SIZE),
                      *new = malloc(SIZE),
                      *dirname = malloc(SIZE);
    
      /* form dest path */
      memset(new, '\0', SIZE);
      sprintf(new, "%s", newdir);
      strcat(new, "/");
      strcat(new, name);
    
      fprintf(stderr, "Saving...%s\n", new);
    
      if ((fd = open(filepath, O_RDONLY)) == -1)
        perror("open");
    
      if ((b_read = read(fd, buf, sizeof(buf))) == -1) {
        perror("read");
        if (errno == EISDIR) { /* path is a directory */
          sprintf(temp, "%s", "./backup ");
          strcat(temp, filepath);
          i = SIZE;
          while (filepath[--i] != '/')
            continue;
          while (filepath[++i] != '\0')
            dirname[k++] = filepath[i];
    
          strcat(temp, " ");
          strcat(temp, newdir);
          strcat(temp, "/");
          strcat(temp, dirname);
          system(temp);
        }
      } else {
        printf("bytes read: %d\n", b_read);
        if ((newfile = open(new, O_RDWR | O_CREAT, 0755)) == -1) {
          perror("open");
        }
    
        if ((b_written = write(newfile, buf, b_read)) == -1) {
          perror("write");
        }
        printf("bytes written: %d\n", b_written);
      }
      close(fd);
      close(newfile);
      return new;
    }
    Last edited by Lateralus; 08-01-2005 at 12:32 PM.
    "So you're one of those condescending UNIX computer users?"

    "Here's a nickel, kid. Get yourself a better computer."

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    You do a lot more dynamic memory allocation than is necessary. If you know orig is going to be SIZE bytes then just declare it as char orig[SIZE]. I would also use PATH_MAX (defined in limits.h) for SIZE. And don't just blindly strcat() without doing bounds checking. You should check before doing the strcat() to make sure it won't overflow your buffer or use something like strncat() instead.
    If you understand what you're doing, you're not learning anything.

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Actually, I was just informed (Thanks, Dave) that PATH_MAX is not a standard macro definition. If your environment doesn't have a PATH_MAX then you can probably come up with something more reasonable than 75 on your own (PATH_MAX is defined as 1024 on my system.) Definitely be sure to do array bounds checking though, regardless.
    If you understand what you're doing, you're not learning anything.

  4. #4
    Prying open my third eye.
    Join Date
    Jun 2005
    Posts
    45
    Thanks for the heads up. I'll look into everything you mentioned.
    "So you're one of those condescending UNIX computer users?"

    "Here's a nickel, kid. Get yourself a better computer."

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I can run the program fine if the executable is in the /usr/bin directory, which is in most peoples PATHs, so is that the best way to use the program? Or is there another way to get around this so that the program can be run from anywhere?
    I wrote a backup program, too, and I put it in another directory which I then added to the path. As long as your program is in the path, you'll be fine.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  2. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  3. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Replies: 3
    Last Post: 03-04-2005, 02:46 PM