What are the possible error codes that can be returned when calling std::filesystem::copy()?
Asked Answered
S

1

6

I can't seem to find a list of error codes that might be passed into the ec parameter for std::filesystem::copy.

cppreference.com seems to indicate that the error codes are OS-specific.
Looking at the Microsoft documentation (As I'm specifically interested in Windows error codes, though I'm sure resources for other OSes would be helpful for others) it looks almost like a copy/paste of the same source documentation without any additional information as to anything Windows specific.

My guess is that the error codes will be the same ones listed here, but there's no information there as to which are relevant to the filesystem, or more specifically the copy() function (beyond educated guessing).

Does anyone have any resources as to potential error codes that might be returned, or, if I have to do this the hard way (and manually try and check for different error scenarios), how do I know if I have an exhaustive list?

Sacellum answered 18/11, 2019 at 9:17 Comment(4)
MS don't document the exhaustive list for WinAPI functions - they just say call GetLastError. As the C++ Runtime Library implementation must eventually call through to the WinAPI level I don't think it's possible to get a complete list of errors. As an example see the docs for CreateFileW learn.microsoft.com/en-gb/windows/win32/api/fileapi/… "...If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError...."Veneaux
If you have specific use-case(s) where you wish to perform different processing depending on the error code you can test for these. However in my experience these are rare. eg what will you do differently for file-not-found; access-denied; no-space; network-failure etc?Veneaux
What are you intending to do with the error? The whole point behind std::error_code's design is that you can still perform reasonable error handling even if you don't know anything about the individual error values.Paisa
There didn't seem to be any information on how to handle the error values (especially in my use case, where I'm not using exceptions), beyond knowing that something went wrong. I wasn't even sure how to check if the function failed simply because there was already a file at the target path, for instance. So Thankyou @ComicSansMS, your answer is exactly what I needed! I'll definitely check out that blog post tooSacellum
P
4

The system specific error codes used by the filesystem library can be found in the __std_win_error enum. Note how the numerical values map 1:1 to the values returned by the Win32 API function GetLastError:

enum class __std_win_error : unsigned long {
    _Success                   = 0, // #define ERROR_SUCCESS                    0L
    _Invalid_function          = 1, // #define ERROR_INVALID_FUNCTION           1L
    _File_not_found            = 2, // #define ERROR_FILE_NOT_FOUND             2L
    _Path_not_found            = 3, // #define ERROR_PATH_NOT_FOUND             3L
    _Access_denied             = 5, // #define ERROR_ACCESS_DENIED              5L
    _Not_enough_memory         = 8, // #define ERROR_NOT_ENOUGH_MEMORY          8L
    _No_more_files             = 18, // #define ERROR_NO_MORE_FILES              18L
    _Sharing_violation         = 32, // #define ERROR_SHARING_VIOLATION          32L
    _Not_supported             = 50, // #define ERROR_NOT_SUPPORTED              50L
    _File_exists               = 80, // #define ERROR_FILE_EXISTS                80L
    _Invalid_parameter         = 87, // #define ERROR_INVALID_PARAMETER          87L
    _Insufficient_buffer       = 122, // #define ERROR_INSUFFICIENT_BUFFER        122L
    _Invalid_name              = 123, // #define ERROR_INVALID_NAME               123L
    _Directory_not_empty       = 145, // #define ERROR_DIR_NOT_EMPTY              145L
    _Already_exists            = 183, // #define ERROR_ALREADY_EXISTS             183L
    _Filename_exceeds_range    = 206, // #define ERROR_FILENAME_EXCED_RANGE       206L
    _Directory_name_is_invalid = 267, // #define ERROR_DIRECTORY                  267L
    _Max                       = ~0UL // sentinel not used by Win32
};

However, you should not ever test against these directly. The whole point of the system_error design is to not have to interpret system specific error_codes directly, but instead only interpret them via their associated error_category.

In particular, the category maps error_code values to error_conditions. The implementation throws an error_code, but the client application should always check for error_conditions. Unlike error_code, error_conditions are portable and do not rely on implementation details.

So here's how you should treat those kinds of errors in code: Check the std::errc for values that you would like to handle programmatically. Then check the error_code against those values:

std::error_code ec;
std::filesystem::copy("source.txt", "destination.txt", ec);
if (ec) {
    if (ec == std::errc::file_exists) {
        // special error handling for file_exists
        // [...]
    } else {
        // generic error handling for all other errors
        // that you don't specifically care about
        std::cerr << "Error: " << ec.message() << "\n";
    }
}

There will likely be some errors left over, but since you almost certainly will not be able to come up with a specialized error handler for those anyway, just put in a catch-all generic error handler for all the error conditions that you don't care about.

Chris Kohlhoff, one of the original authors of the system error library has a great, if somewhat dated, blog series explaining the design and intended use of the error handling mechanism.

Paisa answered 18/11, 2019 at 10:22 Comment(1)
From my experience, Windows can sometimes return ERROR_SUCCESS - I've seen this on rename operations - so if you aren't checking against error codes (which I understand the rationale for), you'll want to frame your logic appropriately and only check for "errors you care about." I'd love to be corrected as this seems fairly confusing.Argol

© 2022 - 2024 — McMap. All rights reserved.