Advertisement
cr1901

Network Backup File Loop

Apr 26th, 2014
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.08 KB | None | 0 0
  1. signed char do_backup(nwBackupParms * parms, char * remote_name, char * local_dir, char * logfile)
  2. {
  3.   char ctrl_file[L_tmpnam];
  4.   dirStack_t dStack;
  5.   dirStruct_t currDir;
  6.   fileStruct_t currFile;
  7.   int8_t rc, done;
  8.   nwBackupCodes nw_rc = SUCCESS;
  9.   int8_t allDirsTraversed = 0;
  10.   int8_t traversalError = 0;
  11.   uint8_t i = 0, j = 0;
  12.   int do_backup_rc = 0;
  13.   int pathEostr;
  14.   /* char driveLetter[4] = {'\0', ':', '\\', '\0'}; /* The drive letter has to be handled separately
  15.         unfortunately... the drive letter must include the trailing
  16.         backslash, while all other path components do not/must not. */
  17.  
  18.   int charsCopied;
  19.   char * path;
  20.   char * path_and_file;
  21.   char * unixPath;
  22.   char * unix_path_and_file;
  23.   char * file_buffer;
  24.   char * out_buffer;
  25.  
  26.   path = malloc(129 * 4);
  27.   file_buffer = malloc(FILE_BUF_SIZE);
  28.   out_buffer = malloc(OUTBUF_SIZE);
  29.   //dummy_outbuf = calloc(OUTBUF_SIZE, 1);
  30.  
  31.   if(path == NULL || file_buffer == NULL || out_buffer == NULL)
  32.   {
  33.     fprintf(stderr, "Could not allocate memory for path or file buffers!\n");
  34.     return -12;
  35.   }
  36.  
  37.   /* Don't bother freeing till end of program- if error, program will terminate
  38.   soon anyway! */
  39.   path_and_file = path + 129;
  40.   unixPath = path_and_file + 129;
  41.   unix_path_and_file = unixPath + 129;
  42.   //char * full_server_path;
  43.   /* rc = sscanf(argv[1], "%c:\\%s", driveLetter[0], path);
  44.   if(rc < 2)
  45.   {
  46.     // Edge case where we only include drive letter.
  47.     if(rc < 1 || argv[1][1] != ':' || argv[1][2] != '\\' || argv[1][3] != '\0')
  48.     {
  49.       fprintf(stderr, "The directory name must be absolute and include the drive letter!\n");
  50.       return EXIT_FAILURE;
  51.     }
  52.   } */
  53.  
  54.  
  55.   if(initDirStack(&dStack)) {
  56.     fprintf(stderr, "Directory Stack Initialization failed!\n");
  57.     return -1;
  58.   }
  59.  
  60.   if(!strcpy(path, local_dir))
  61.     /* if(strncpy(path, argv[1], DIR_MAX_PATH + 1) >= (DIR_MAX_PATH + 1)) */
  62.   {
  63.     /* Shouldn't fail... but Heartbleed convinces me to
  64.     code defensively. */
  65.     fprintf(stderr, "Specified path name is too long...\n"
  66.             "Actually if we're got this error on DOS, we have more serious\n"
  67.             "trouble than just a bad path!\n");
  68.   }
  69.  
  70.   pathEostr = strlen(path);
  71.   if(path[pathEostr - 1] == 92) {
  72.     path[pathEostr - 1] = '\0';
  73.     pathEostr--;
  74.     /* pathEostr now points to the root path's NULL
  75.     terminator. */
  76.   }
  77.  
  78.   //full_unix_path = malloc(strlen(parms-> strlen(remote_name) + );
  79.  
  80.   if(traversalError = pushDir(&dStack, &currDir, path)) {
  81.     fprintf(stderr, "Initial directory push failed!\n");
  82.     return -2;
  83.   }
  84.  
  85.   if(openDir(path, &currDir, &currFile)) {
  86.     fprintf(stderr, "Directory open failed!\n");
  87.     return -3;
  88.   }
  89.  
  90.  
  91.   nw_rc = initRemote(parms);
  92.   if(nw_rc != SUCCESS)
  93.   {
  94.     do_backup_rc = -4;
  95.   }
  96.  
  97.   nw_rc = mkDirRemote(remote_name);
  98.   if(!(nw_rc == SUCCESS || nw_rc == TARGET_EXIST))
  99.   {
  100.     do_backup_rc = -5;
  101.   }
  102.  
  103.   nw_rc = chDirRemote(remote_name);
  104.   if(!(nw_rc == SUCCESS))
  105.   {
  106.     do_backup_rc = -6;
  107.   }
  108.  
  109.  
  110.  
  111.   while(!allDirsTraversed && do_backup_rc == 0)
  112.   {
  113.     /* int retry_count = 0; */
  114.     int retry_count;    
  115.     retry_count = 0;
  116.    
  117.     charsCopied = snprintf(path_and_file, DIR_MAX_PATH + 1, "%s\\%s", path, currFile.name);
  118.     if(charsCopied >= DIR_MAX_PATH + 1) {
  119.       traversalError = 1;
  120.       fprintf(stderr, "Directory traversal error, LINE %u!\n", __LINE__);
  121.       do_backup_rc = -8;
  122.       break;
  123.     }
  124.     //printf("Current Dir+file: %s\n", path_and_file);
  125.     /* Strip the root from the path... the "+1" reflects
  126.     that the NULL terminator of the root coincides with the path
  127.     separator in path. */
  128.  
  129.    
  130.     unixPath[0] = '\0';
  131.     if(createUnixName(unixPath, &path[pathEostr + 1]) == NULL) {
  132.       fprintf(stderr, "Unix directory name creation failed!\n");
  133.       do_backup_rc = -7;
  134.       break;
  135.     }
  136.    
  137.    
  138.     if(strlen(unixPath) == 0) /* We are back at directory root if here */
  139.     {
  140.       sprintf(unix_path_and_file, "%s", currFile.name);
  141.     }
  142.     else
  143.     {
  144.       sprintf(unix_path_and_file, "%s/%s", unixPath, currFile.name);
  145.     }
  146.    
  147.     if(currFile.attrib == (currFile.attrib & _A_SUBDIR)) {
  148.       /* The two relative directories can be safely
  149.       ignored. */
  150.       if(!(strcmp(currFile.name, ".") == 0 \
  151.            || strcmp(currFile.name, "..") == 0)) {
  152.        
  153.         strcpy(path, path_and_file);
  154.         traversalError = pushDir(&dStack, &currDir, path);
  155.         if(traversalError) {
  156.           fprintf(stderr, "Directory traversal error, LINE %u!\n", __LINE__);
  157.           do_backup_rc = -9;
  158.           break;
  159.         }
  160.  
  161.         if(openDir(path, &currDir, &currFile)) {
  162.           fprintf(stderr, "Directory traversal error, LINE %u!\n", __LINE__);
  163.           do_backup_rc = -10;
  164.           break;
  165.         }
  166.         //fprintf(stderr, "\n");
  167.        
  168.         fprintf(stderr, "NW: Creating directory %s...\n", unix_path_and_file);
  169.         do{
  170.           if(retry_count)
  171.           {
  172.             fprintf(stderr, "NW: Retrying operation...\n");
  173.           }
  174.           nw_rc = mkDirRemote(unix_path_and_file);
  175.           //nw_rc = SUCCESS;
  176.           retry_count++;
  177.         }while(nw_rc != SUCCESS && retry_count <= 3);
  178.        
  179.         if(retry_count > 3)
  180.         {
  181.           do_backup_rc = -11;
  182.         }
  183.         else
  184.         {
  185.           retry_count = 0;
  186.         }
  187.        
  188.         continue; /*A new open directory already will
  189.         have the first file open, just like before
  190.         the main loop. So we don't skip it, don't get
  191.         the next file after opening a directory.
  192.         On DOS at least, not including
  193.         this continue is harmless, and saves a few cycles,
  194.         as DOS will always return "." first, which would
  195.         be skipped anyway!. */
  196.       }
  197.     }
  198.    
  199.     else { /* We have a file... send it. */
  200.       FILE * currFp;
  201.       currFp = fopen(path_and_file, "rb");
  202.       if(currFp == NULL)
  203.       {
  204.         fprintf(stderr, "Read error on file: %s! Not continuing.", path_and_file);
  205.         do_backup_rc = -13;
  206.       }
  207.       else
  208.       {
  209.         int8_t local_error = 0;
  210.         //setvbuf(currFp, file_buffer, _IOFBF, 4096);
  211.         fprintf(stderr, "NW: Storing file %s...\n", unix_path_and_file);
  212.        
  213.         done = 0;
  214.         while(!done && !local_error && retry_count <= 3)
  215.         {
  216.           int8_t send_remote_rc;
  217.           if(retry_count)
  218.           {
  219.             fprintf(stderr, "NW: Retrying operation...\n");
  220.           }
  221.          
  222.           send_remote_rc = send_file(currFp, unix_path_and_file, file_buffer);
  223.           switch(send_remote_rc)
  224.           {
  225.           case 0:
  226.             done = 1;
  227.             break;
  228.           case -2:
  229.             fprintf(stderr, "Read error on file: %s! Not continuing.", path_and_file);
  230.             local_error = 1; /* Local file error. */
  231.             break;
  232.           case -1: /* Recoverable error. */
  233.           default:
  234.             break;
  235.           }
  236.           retry_count++;
  237.         }
  238.        
  239.         if(local_error) /* If file error, we need to break out. */
  240.         {
  241.           do_backup_rc = -15;
  242.         }
  243.         else
  244.         {
  245.           if(retry_count > 3)
  246.           {
  247.             do_backup_rc = -14;
  248.           }
  249.           else
  250.           {
  251.             retry_count = 0;
  252.           }
  253.         }
  254.       }
  255.       fclose(currFp);
  256.     }
  257.  
  258.     /* Only perform another iteration of the file loop
  259.     when there is in fact another file to send. If there are no
  260.     files left, we know to break as well. The while loop should
  261.     only execute when a parent directory has finished traversal at
  262.     the same time as its child(ren). */
  263.     if(!do_backup_rc) /* Don't bother if we got here and an error occured,
  264.       we are about to break anyway. */
  265.     {
  266.       while(getNextFile(&currDir, &currFile) && !allDirsTraversed) {
  267.         closeDir(&currDir);
  268.         if(popDir(&dStack, &currDir, path)) {
  269.           allDirsTraversed = 1;
  270.         }
  271.       }
  272.     }
  273.   }
  274.  
  275.   if(do_backup_rc)
  276.   {
  277.     fprintf(stderr, "Full backup failed with status code %d.\n", do_backup_rc);
  278.   }
  279.   else
  280.   {
  281.     fprintf(stderr, "Full backup completed successfully.\n");
  282.   }
  283.   closeRemote();
  284.   return 0;
  285. }
  286.  
  287.  
  288. int8_t send_file(FILE * fp, char * remote_name, uint8_t * out_buffer)
  289. {
  290.   nwFileHandle nwFp = NULL;
  291.   nwBackupCodes open_rc;
  292.   int8_t remote_rc = 0; /* Assume success... */
  293.  
  294.   open_rc = openRemoteFile(nwFp, remote_name, 0);
  295.  
  296.   if(!open_rc) /* If we opened the file ok, read it to the remote */
  297.   {
  298.     nwBackupCodes close_rc;
  299.     nwBackupCodes send_rc;
  300.     uint16_t chars_read;
  301.     int8_t done_read;
  302.     uint16_t actual_chars_sent;
  303.     int8_t local_file_error;
  304.     //long test;
  305.     unsigned long total_size = 0;
  306.    
  307.     done_read = 0;
  308.     send_rc = 0;
  309.     local_file_error = 0;
  310.     while(!done_read && !send_rc && !local_file_error)
  311.     {
  312.       chars_read = fread(out_buffer, 1, OUTBUF_SIZE, fp);
  313.       //fprintf(stderr, "%d chars read\n", chars_read);
  314.      
  315.       if(chars_read < OUTBUF_SIZE) /* Send the remaining characters... */
  316.       {
  317.         if(feof(fp))
  318.         {
  319.           uint16_t chars_left = chars_read;
  320.           //fprintf(stderr, "EOF: Finish sending characters...");
  321.           //Race condition if (all these) fprintfs and sendDataRemote commented out.
  322.           while(!send_rc && chars_left)
  323.           {
  324.             //send_rc = sendDataRemote(nwFp, out_buffer, chars_left, &actual_chars_sent);
  325.             send_rc = sendDataRemote(nwFp, out_buffer, chars_left, &actual_chars_sent);
  326.             //send_rc = SUCCESS;
  327.             //actual_chars_sent = chars_left;
  328.             //fprintf(stderr, "%d chars sent\n", actual_chars_sent);
  329.             total_size += actual_chars_sent;
  330.             //fprintf(stderr, "%lu total bytes sent...\r", total_size);
  331.             chars_left -= actual_chars_sent;
  332.           }
  333.          
  334.           if(!send_rc)
  335.           {
  336.             done_read = 1;
  337.           }
  338.         }
  339.         else /* A file error occurred. */
  340.         {
  341.           local_file_error = 1;
  342.         }
  343.       }
  344.       else
  345.       {
  346.         send_rc = sendDataRemote(nwFp, out_buffer, chars_read, &actual_chars_sent);
  347.         total_size += actual_chars_sent;
  348.         //fprintf(stderr, "%lu total bytes sent...\r", total_size);
  349.         //send_rc = 0;
  350.         //actual_chars_sent = OUTBUF_SIZE;
  351.         //fprintf(stderr, "%d chars sent\n", actual_chars_sent);
  352.         if(actual_chars_sent < chars_read) /* This is okay, and will happen sometimes... */
  353.         {
  354.           /* Barring transient errors, this cast should aways work...
  355.           chars_sent will likely not be > 536 and chars_read is bounded by
  356.           OUTBUF_SIZE. */
  357.          
  358.           fseek(fp, (long) ((short) actual_chars_sent - (short) chars_read), SEEK_CUR);
  359.          
  360.           /* Just reset the file pointer back the number of characters that
  361.           weren't sent */
  362.          
  363.           /* Casting fun
  364.           //test = (long) ((short) actual_chars_sent - (short) chars_read); //Good
  365.           //test = (long) (actual_chars_sent - chars_read); //Bad
  366.           //(long) ((short) actual_chars_sent - (short) chars_read); //Good
  367.           //(long) (actual_chars_sent - chars_read); //Good? Apparently cast is meaningless...
  368.           //fseek(fp, (long) ((short) actual_chars_sent - (short) chars_read), SEEK_CUR); //Good
  369.           //fseek(fp, (long) (actual_chars_sent - chars_read), SEEK_CUR); //Bad
  370.           */
  371.         }
  372.       }
  373.     }
  374.    
  375.     if(!local_file_error)
  376.     {
  377.       /* We should close the file even if send_rc errored out! */
  378.       close_rc = closeRemoteFile(nwFp);
  379.       if(!close_rc && !send_rc)
  380.       {
  381.         fprintf(stderr, "File sent okay...\n");
  382.         remote_rc = 0; /* If we successfully sent the file, we are done. */
  383.       }
  384.       else
  385.       {
  386.         fprintf(stderr, "Open error code: %d, Send error code: %d, Close error code: %d\n", open_rc, send_rc, close_rc);
  387.         remote_rc = -1; /* Worth retrying transfer. */
  388.       }
  389.     }
  390.     else
  391.     {
  392.       close_rc = closeRemoteFile(nwFp);
  393.       remote_rc = -2; /* Do not retry transfer. */
  394.     }
  395.   }
  396.   else
  397.   {
  398.     remote_rc = -1;
  399.   }
  400.  
  401.   return remote_rc;
  402. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement