File rename errors if target file exists

The docs for int playdate->file->rename(const char* from, const char* to); state:

Renames the file at from to to. It will overwrite the file at to without confirmation. It does not create intermediate folders. Returns 0 on success, or -1 in case of error.

(Emphasis mine)

But when running code like so:

SDFile* file1 = playdate->file->open("test1.txt", kFileWrite);
playdate->file->write(file1, "test", 4);
playdate->file->close(file1);

SDFile* file2 = playdate->file->open("test2.txt", kFileWrite);
playdate->file->write(file2, "test", 4);
playdate->file->close(file2);

int ret = playdate->file->rename("test1.txt", "test2.txt");

ret will be -1. And playdate->file->geterr() will return File exists.

Tested in the Windows simulator and on device with SDK 2.7.3.

Workaround is to unlink the file first, which can also fail if file to overwrite doesn't exist yet, so it's error must be ignored in those situations. You can't safely pre-check if it exists or not with stat as a file may exist with the same name in the .pdx, see here.

This may just be a documentation bug as the equivelant Lua function does not note the same functionality.

Thanks for the report, this is a Windows-ism and I'll try and get the API closer to the device behavior. Thanks again.

1 Like

I see this marked as fixed in 2.7.4 but only noting Windows, and I think I misread your comment - for me this orignally failed on device too and still seems to? I get an unknown uC-FS error: 0704 error from geterr on device. It's possible I'm doing something wrong though still?

0x704 is a "file already exists" error, which seems to indicate that pd->file->rename doesn't delete the previous destination file, instead attempting to rename the file immediately and failing when it doesn't work.

Strange that the uC-FS error handler doesn't catch this one though.

HA, so it fails on device and Windows but the docs say it will overwrite...wow. OK. The behavior in the docs is what macOS does which is probably how it got documented. I personally thing that is very odd behavior and prefer the file exists error but I'll see what I can do.

Yeah to be honest I'm ok either way, though I'd rather be able to write fully "correct" error handling without needing to string compare or ignore the error a function returns.

Like e.g. right now you can't "safely" stat if a file is in the pdx or the data dir, so you can't know if there's a file to rename, so even if you unlink the destination you might fail the rename (no source).

It's totally workaroundable in all of my use cases though, so maybe it's just my code "correctness" pedantry.