0

I'm developing a little updater for my framework. In particular the file is written in C++ and when i try to download a file using the following code the fopen function returns NULL. But the thing is that i tested this software on different machines with the same OS (Windows 10) and on few of them they returns NULL, the others just download and write the file correctly. Do you have any ideas? I've also tried to TRIM the filename to avoid invisible characters. Here's the code to download the file i used:

std::vector<unsigned char> resp = http_request(url, "GET", NULL, NULL, "", user_agent);
if (resp.empty()) {
    send_output("ERROR: No response while downloading: " + url);
    return;
}
string filename = url.substr(url.rfind("/") + 1);
filename = trim(filename);
if (filename.empty()) {
    filename = "downloaded";
}
FILE* f = fopen(filename.c_str(), "wb");
if (f == NULL) {
    log("ERROR: Could not open file for writing: " + filename);
    return;
}
fwrite(&resp[0], 1, resp.size(), f);
fclose(f);

Thanks guys for the help!

TheSphinx
  • 47
  • 1
  • 7
  • 3
    http://www.cplusplus.com/reference/cstdio/fopen/ : "On most library implementations, the errno variable is also set to a system-specific error code on failure." What is it? – Vlad Feinstein Aug 05 '20 at 18:08
  • Or, you could use the Win32 `CreateFile()` directly, and if it fails then check with `GetLastError()` to learn why. What is the actual value of `filename` when `fopen()` fails? Maybe it is not what you are expecting it to be. Or, more likely, it is probably a relative path that is trying to write the file to a folder you don't have access to. Don't use relative paths, use absolute paths instead, for instance `filename = ...; filename = "C:\\path that I control\\" + filename; FILE* f = fopen(filename.c_str(), "wb"); ...` – Remy Lebeau Aug 05 '20 at 18:11
  • 5
    There could be *a ton* of reasons for you not being able to open/create a specific file. Some reasons (not exhaustive); 1) The filesystem is read-only for some reason. 2) the current user does not have permission to create or access a file in that location. 3) the filesystem is full. 4) the location you want to create/open the file in does not exist. 5) the user physically unplugged the harddrive. And much, much more... – Jesper Juhl Aug 05 '20 at 18:13
  • On windows, I'd suggest using procmon, which is an amazing debugging tool: https://learn.microsoft.com/en-us/sysinternals/downloads/procmon However, that's only for debugging purposes. "Production" code should handle errors like others have commented here. – chakaz Aug 05 '20 at 18:15
  • 2
    `url.rfind("/")` -- If that character is not found, then what do you do? Looks like your method is not bulletproof in multiple ways. – PaulMcKenzie Aug 05 '20 at 18:16
  • 4
    Why don't you ask your computer why `fopen` fails? `if (f == nullptr) { std::cerr << std::strerror(errno) << std::endl; }` – rustyx Aug 05 '20 at 18:19
  • @rustyx I've made as you said and actually i got : Permission Denied. For some reasons in each folder i execute the updater i can't actually download a simple txt or a picture file i think this is due to some system permissions? – TheSphinx Aug 05 '20 at 18:53
  • Using a relative path name is not ever not a mistake. Choosing an incomplete character set doesn't help. – IInspectable Aug 05 '20 at 19:13
  • Many Windows error codes map to POSIX `EACCES` (13). Please also check the associated Windows error in [`_doserrno`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/errno-doserrno-sys-errlist-and-sys-nerr?view=vs-2019). If it's `ERROR_ACCESS_DENIED` (5), many NT status codes map to this error. If you're familiar with runtime linking via `GetModuleHandleW` and `GetProcAddress`, also check the last NT status code via `RtlGetLastNtStatus()` -- linked from "ntdll.dll" -- called immediately after `fopen`. Unlike `_doserrno`, the last NT status value may not be relevant, but it may help. – Eryk Sun Aug 05 '20 at 19:20
  • 1
    On Windows I believe you'll get "Permission denied" also for the case when a file is already open with an incompatible share mode (I believe `GetLastError()` return code 32, `ERROR_SHARING_VIOLATION`). – rustyx Aug 05 '20 at 19:41
  • Understood. I find this thing weird by the way for the reason that on other workstations with the same Windows version it works without errors. I've tried to run the updater with admin rights but nothing has changed so i believe all stands on some permissions. Really don't know how to work around this trouble. – TheSphinx Aug 06 '20 at 05:16

0 Answers0