user2630969
user2630969

Reputation: 57

Issue with snprintf "date" and file locations

I have two issues I would like help with on solving. I have a program that captures the given information in a key file. In my case, the information is for backing up different directories, to a given location, for X amount of days.

The program will compress the source directories, then push them to a temporary back up location. Then it will check to see if the files exist before moving on.

Here is where my two issues start to come into play.

The temporary backup files will now be pushed to a folder that loops and creates the required amount of folders for the duration of time. This works great if only on the desktop. My issue is I want to be able to put these files wherever I please. When I do that it will error and say "directory 1 already exists" and stop. (This is the first day of the duration).

Also I want to rename the backup files to the current date they were created. When i do this it will show the names as "Success242483413.tgz" instead of for example 082313. When I rename the file in the temp directory it appears to work but then the issue is the check to see if file exists doesn't know how to read the date, and errors.

Here is a snippet from my code, the main() where I am having these two issue. I can post up all the code if it would help to see it run to better understand. The issue is the bold area.

EDIT: I cant bold code, so its the areas with comments around them.

Thank you and sorry for the long post!

int main()
{
    //The key file, editable to your requirements.
    parseCodeFile cfg("key.cfg");
    std::string source = cfg.getValueOfKey<std::string>("source");
    std::string tempDestination = cfg.getValueOfKey<std::string>("tempDestination");
    std::string destination = cfg.getValueOfKey<std::string>("destination");
    int duration = cfg.getValueOfKey<int>("duration");
    int count, placeHolder, placeHolderAdvanced;
    count = 1;
    char command[256];
    snprintf(command, 256, "mkdir %s", tempDestination.c_str());
    system(command);
    // START RELEVANT
    snprintf(command, 256, "tar -cvzf %s/backup.tgz %s", tempDestination.c_str(), source.c_str());
    system(command);
    // END RELEVANT
    //Determines if the backup file exists. If not, closes the program.
    ifstream backupExists(tempDestination.c_str());
    if(backupExists.good())
    {
        std::cout << "\nCurrent backup.tgz file exists!\n\n";
    }
    else
    {
        std::cout << "\nFUUUUU NO FILE!\n";
        return 0;
    }
    //Removes the last folder in the group.
    snprintf(command, 256, "rm -rf %i", duration);
    system(command);
    while(count<duration)
    {
        //Holds the value that descends.
        placeHolder = duration - count;
        //Holds the value that ascends.
        placeHolderAdvanced = placeHolder + 1;
        snprintf(command, 256, "mv %i %i", placeHolder, placeHolderAdvanced);
        system(command);
        count++;
    }
    // START RELEVANT
    snprintf(command, 256, "mkdir %i", 1);
    system(command);
    snprintf(command, 256, "mv %s/backup.tgz %s/1", tempDestination.c_str(), destination.c_str());
    system(command);
    snprintf(command, 256, "mv %s/1/backup.tgz %s/1/`date +%m%d%y`.tgz", destination.c_str(), destination.c_str());
    system(command);
    // END RELEVANT
    return 0;
}

Upvotes: 1

Views: 169

Answers (3)

user2630969
user2630969

Reputation: 57

Okay so I figured out the issue with the folders. When the files were getting moved to the new folder, the count of mkdir 1 was still sending those to the desktop. Causing the conflict. Here is what I did:

I added // CHANGE comments with anything that has changed.

int main()
{
    //The key file, editable to your requirements.
    parseCodeFile cfg("key.cfg");
    std::string source = cfg.getValueOfKey<std::string>("source");
    std::string tempDestination = cfg.getValueOfKey<std::string>("tempDestination");
    std::string destination = cfg.getValueOfKey<std::string>("destination");
    int duration = cfg.getValueOfKey<int>("duration");
    int count, placeHolder, placeHolderAdvanced;
    count = 1;
    char command[256];
    // START CHANGE
    string Date = "backup-`date '+%m%d%y'`.tgz";                 // CHANGE
    snprintf(command, 256, "mkdir %s", tempDestination.c_str());
    system(command);
    snprintf(command, 256, "mkdir %s", destination.c_str());     // CHANGE
    system(command);                                             // CHANGE
    // END CHANGE
    snprintf(command, 256, "tar -cvzf %s/backup.tgz %s", tempDestination.c_str(), source.c_str());
    system(command);
    //Determines if the backup file exists. If not, closes the program.
    ifstream backupExists(tempDestination.c_str());
    if(backupExists.good())
    {
        std::cout << "\nCurrent backup.tgz file exists!\n\n";
    }
    else
    {
        std::cout << "\nFUUUUU NO FILE!\n";
        return 0;
    }
    //Removes the last folder in the group.
    snprintf(command, 256, "rm -rf %i", duration);
    system(command);
    while(count<duration)
    {
        //Holds the value that descends.
        placeHolder = duration - count;
        //Holds the value that ascends.
        placeHolderAdvanced = placeHolder + 1;
        // START CHANGE
        snprintf(command, 256, "mv %s/%i %s/%i", destination.c_str(),placeHolder, destination.c_str(),placeHolderAdvanced);
        system(command);
        // END CHANGE
        count++;
    }
    // START CHANGE
    snprintf(command, 256, "mkdir %s%s",destination.c_str(),"/1");
    system(command);
    snprintf(command, 256, "mv %s/backup.tgz %s/1/%s", tempDestination.c_str(), destination.c_str(),Date.c_str());
    system(command);
    // END CHANGE
    return 0;
}

Upvotes: 0

sehe
sehe

Reputation: 393477

And in case you really wished it to be C++ code, here's a tested, somewhat sane C++11 version:

  • TODO use execve or similar instead of system (requires a dirExists() function)
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <cassert>
#include <cstring>

//////////////////////////////////////////////
// Utilities
std::string safe_quote(std::string const& v);
std::string getbackup_datename();
void run_command(std::string const& cmd);

//////////////////////////////////////////////
// Variadic command helper, does quoting
struct allow_err {};

void run_command(std::string const& cmd, allow_err) {
    run_command(cmd + " || true");
}

template <typename Arg, typename... Args>
   void run_command(std::string const& cmd, Arg arg1, Args&&... args) {
    std::ostringstream oss;
    oss << cmd << " " << safe_quote(arg1);
    run_command(oss.str(), std::forward<Args>(args)...);
}
// End Helpers / Utilities
//////////////////////////////////////////////

int main()
{
    //The key file, editable to your requirements.
    std::string source          = "/tmp/q";
    std::string tempDestination = "/tmp/q2_temp";
    std::string destination     = "/tmp/q2";
    int duration                = 6;

    std::string newname = tempDestination + "/" + getbackup_datename();
    {
        run_command("mkdir -p", tempDestination, destination);
        run_command("tar -czf", newname, source);
    }

    auto destdir = [=](int i) { return destination + "/" + std::to_string(i); };

    run_command("rm -rf", destdir(duration));

    for (int count=duration-1; count>0; --count)
        run_command("[ -d " + safe_quote(destdir(count)) + " ] && mv ", destdir(count), destdir(count+1), allow_err());

    run_command("mkdir -p", destdir(1));
    run_command("mv", newname, destdir(1) + '/');
}

//////////////////////////////////////////////
// Utilities implementations
std::string safe_quote(std::string const& v) 
{ 
    assert(v.find_first_of("'\"") == std::string::npos); // not implemented
    return "'" + v + "'"; 
}

void run_command(std::string const& cmd)
{
    std::string wrapped = "bash -c \"" + cmd + "\"";
    if (int exitcode = system(wrapped.c_str()))
    {
        std::cerr << "Command failed: " << wrapped << "\n";
        exit(exitcode);
    }
    //// For debug:
    //std::cout << "+" << cmd << "\n";
}

std::string getbackup_datename()
{
    char buf[20] = {0};
    auto t = time(NULL);
    strftime(buf, 20, "backup%m%d%y.tgz", localtime(&t));
    return buf;
}

Upvotes: 2

sehe
sehe

Reputation: 393477

Here's a sane shell script to do the job:

#!/bin/bash
set -e
source key.cfg

mkdir -p "$tempDestination" "$destination"
newname="$tempDestination/$(date +"backup-%m%d%y.tgz")"
tar -czf "$newname" "$source"

# rotate backups
rm -rf "$destination/$duration" # Removes the last folder in the group.
for((count=$((duration-1)); $count > 0; count=$count-1))
do [ -d "$destination/$count" ] && 
        mv "$destination/$count" "$destination/$(($count + 1))"
done

mkdir -p "$destination/1" && mv "$newname" "$destination/1/"

Notes

  • you rm -rf the wrong folder (folder 6 exists under $destination, not in the current directory!)
  • you probably intended to check for the temp backup.tgz. Instead, you accidentally checked for the tempDestination folder only...
  • I used the set -e flag to abort on any error (so if tar failed, the script won't continue)
  • I used date to format the archive name. man date
  • It will read a key.cfg file, expecting a content like

    source="/tmp/q"
    tempDestination="/tmp/q2_temp"
    destination="/tmp/q2"
    duration=6
    

Upvotes: 1

Related Questions