Question

I have the following code:

void CommandRenHandler::HandleCommand(Socket* socket, std::vector<std::string>& rvParams){
    if (rvParams.size() < 2){
        socket->writeline("Not enough parameters specified");
        return;
    }

    std::string filePath = BASE_DIRECTORY;
    filePath.append(rvParams.at(0));
    std::string filePath2 = BASE_DIRECTORY;
    filePath2.append(rvParams.at(1));
    int result = rename(filePath.c_str(), filePath2.c_str());

    // TEST
    std::cout << filePath << " " << filePath2 << std::endl << "result: " << result << std::endl;

    if (result == 0)
        socket->writeline("File renamed");
    else
        socket->writeline("Could not rename file");
}

In this function I receive two file-paths with the files that need to be renamed. I've added the TEST cout.

I've got 1 file that need to be renamed. Here are the input and output of my tests:

1 (Renaming the file manually - WORKS AS INTENTED):

In the console:

REN one\image.png one\new_image.png

Debugging:

filePath = "C:\\...\\one\\image.png"
filePath2 = "C:\\...\\one\\new_image.png"
result = 0;

Test output:

C:\...\one\image.png C:\...\one\new_image.png result: 0

2 (Renaming the file back manually - WORKS AS INTENTED):

In the console:

REN one\new_image.png one\image.png

Debugging:

filePath = "C:\\...\\one\\new_image.png"
filePath2 = "C:\\...\\one\\image.png"
result = 0;

Test output:

C:\...\one\new_image.png C:\...\one\image.png result: 0

3 (Using SYNC which uses the same rename - DOES NOT WORK):

In the console:

SYNC one one

(This method checks if a file is changed or just renamed. In this case it's renamed and it will send the info below to the Rename function, just like with a regular REN as above.)

Debugging:

filePath = "C:\\...\\one\\image.png"
filePath2 = "C:\\...\\one\\new_image.png"
result = -1;

Test output:

C:\...\one\image.png C:\...\one\image.png result: -1

1 (Rename the same file again, exactly like in step 1, but this time we also get an error again - DOES NOT WORK ANYMORE)

In the console:

REN one\image.png one\new_image.png

Debugging:

filePath = "C:\\...\\one\\image.png"
filePath2 = "C:\\...\\one\\new_image.png"
result = -1;

Test output:

C:\...\one\image.png C:\...\one\new_image.png result: -1

So, my question is: Why does the rename function of C++ works fine at first, but then fails during the SYNC function and after that I'm also not able to use the REN function anymore manually..

TL;DR: Can someone see what the problem is with just the parts of code provided? Or is there any way to see what caused the rename error? Because just -1 is kinda useless as a debug-result..

Thanks in advance.

PS: Here is the SYNC code, just in case:

std::vector<std::string> vParams;
// Check wether file is completely different or just renamed
std::string oldFile = FileJustRenamed(file);
if (oldFile != "") {
    vParams.push_back(std::string("REN"));
    vParams.push_back(oldFile);
    vParams.push_back(file);

    std::cout << "Renaming " << file << std::endl;
    ren_handler->HandleCommand(socket, vParams);
}

PSS: Yes, the paths do match exactly. The "..." in the filePaths is for privacy reasons.

And for those wondering: The C++ is coded in Windows, not Linux.

Edit: The first rvParam ("REN") will be removed in a factory-class, which creates the CommandRenHandler. There the HandleCommand function will be called with the first rvParam (in this case "REN") removed. So rvParams.at(0) is the first filePath and rvParams.at(1) is the second filePath.

Sorry I didn't mentioned that before in my code.

Was it helpful?

Solution 2

After Nemanja Boric's tip the file might still be open somewhere, I looked through my code. It turned out I still had an ifstream open (but this wasn't the problem, since the same problem still occurred after closing it).

Then I continued looking and noticed I didn't close another stream somewhere else in my code, because of an early return-statement.

TL;DR: Had to close an open stream in my code in order to rename the file.

OTHER TIPS

Well, you have off-by-one error:

if (oldFile != "") {
    vParams.push_back(std::string("REN"));
    vParams.push_back(oldFile);
    vParams.push_back(file);

    std::cout << "Renaming " << file << std::endl;
    ren_handler->HandleCommand(socket, vParams);
}

Here, vParams.at(0) is "REN" string, which you're using in rename:

std::string filePath = BASE_DIRECTORY;
filePath.append(rvParams.at(0));           // THIS IS "REN" and not the actual filename.
std::string filePath2 = BASE_DIRECTORY;
filePath2.append(rvParams.at(1));
int result = rename(filePath.c_str(), filePath2.c_str());

So, based on what I see, I guess this is the correct implementation of HandleCommand:

void CommandRenHandler::HandleCommand(Socket* socket, std::vector<std::string>& rvParams){
    if (rvParams.size() < 3){
        socket->writeline("Not enough parameters specified");
        return;
    }


    if(rvParams.at(0) == "REN")
    {
        std::string filePath = BASE_DIRECTORY;
        filePath.append(rvParams.at(1));
        std::string filePath2 = BASE_DIRECTORY;
        filePath2.append(rvParams.at(2));
        int result = rename(filePath.c_str(), filePath2.c_str());

        // TEST
        std::cout << filePath << " " << filePath2 << std::endl << "result: " << result << std::endl;

        if (result == 0)
            socket->writeline("File renamed");
       else
            socket->writeline("Could not rename file");
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top