Merge pull request #10973 from hpvb/fix-file-access-unix

Make UNIX file access more correct
This commit is contained in:
Rémi Verschelde 2017-09-05 00:33:20 +02:00 committed by GitHub
commit 27feafbe12

View file

@ -36,12 +36,17 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#if defined(UNIX_ENABLED)
#include <unistd.h>
#endif
#ifndef ANDROID_ENABLED #ifndef ANDROID_ENABLED
#include <sys/statvfs.h> #include <sys/statvfs.h>
#endif #endif
#ifdef MSVC #ifdef MSVC
#define S_ISREG(m) ((m)&_S_IFREG) #define S_ISREG(m) ((m)&_S_IFREG)
#include <io.h>
#endif #endif
#ifndef S_ISREG #ifndef S_ISREG
#define S_ISREG(m) ((m)&S_IFREG) #define S_ISREG(m) ((m)&S_IFREG)
@ -85,13 +90,19 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
//printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data()); //printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
struct stat st; struct stat st;
if (stat(path.utf8().get_data(), &st) == 0) { int err = stat(path.utf8().get_data(), &st);
if (err)
if (!S_ISREG(st.st_mode))
return ERR_FILE_CANT_OPEN; return ERR_FILE_CANT_OPEN;
};
if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) { switch (st.st_mode & S_IFMT) {
case S_IFLNK:
case S_IFREG:
break;
default:
return ERR_FILE_CANT_OPEN;
}
if (is_backup_save_enabled() && (p_mode_flags & WRITE) && !(p_mode_flags & READ)) {
save_path = path; save_path = path;
path = path + ".tmp"; path = path + ".tmp";
//print_line("saving instead to "+path); //print_line("saving instead to "+path);
@ -108,15 +119,19 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
return OK; return OK;
} }
} }
void FileAccessUnix::close() { void FileAccessUnix::close() {
if (!f) if (!f)
return; return;
fclose(f); fclose(f);
f = NULL; f = NULL;
if (close_notification_func) { if (close_notification_func) {
close_notification_func(path, flags); close_notification_func(path, flags);
} }
if (save_path != "") { if (save_path != "") {
//unlink(save_path.utf8().get_data()); //unlink(save_path.utf8().get_data());
@ -131,10 +146,12 @@ void FileAccessUnix::close() {
ERR_FAIL_COND(rename_error != 0); ERR_FAIL_COND(rename_error != 0);
} }
} }
bool FileAccessUnix::is_open() const { bool FileAccessUnix::is_open() const {
return (f != NULL); return (f != NULL);
} }
void FileAccessUnix::seek(size_t p_position) { void FileAccessUnix::seek(size_t p_position) {
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
@ -143,29 +160,39 @@ void FileAccessUnix::seek(size_t p_position) {
if (fseek(f, p_position, SEEK_SET)) if (fseek(f, p_position, SEEK_SET))
check_errors(); check_errors();
} }
void FileAccessUnix::seek_end(int64_t p_position) { void FileAccessUnix::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
last_error = OK;
if (fseek(f, p_position, SEEK_END)) if (fseek(f, p_position, SEEK_END))
check_errors(); check_errors();
} }
size_t FileAccessUnix::get_pos() const { size_t FileAccessUnix::get_pos() const {
size_t aux_position = 0; ERR_FAIL_COND_V(!f, 0);
if (!(aux_position = ftell(f))) {
last_error = OK;
int pos = ftell(f);
if (pos < 0) {
check_errors(); check_errors();
}; ERR_FAIL_V(0);
return aux_position; }
return pos;
} }
size_t FileAccessUnix::get_len() const { size_t FileAccessUnix::get_len() const {
ERR_FAIL_COND_V(!f, 0); ERR_FAIL_COND_V(!f, 0);
FileAccessUnix *fau = const_cast<FileAccessUnix *>(this); int pos = ftell(f);
int pos = fau->get_pos(); ERR_FAIL_COND_V(pos < 0, 0);
fau->seek_end(); ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0);
int size = fau->get_pos(); int size = ftell(f);
fau->seek(pos); ERR_FAIL_COND_V(size < 0, 0);
ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0);
return size; return size;
} }
@ -202,22 +229,36 @@ Error FileAccessUnix::get_error() const {
void FileAccessUnix::store_8(uint8_t p_dest) { void FileAccessUnix::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
fwrite(&p_dest, 1, 1, f); ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1);
} }
bool FileAccessUnix::file_exists(const String &p_path) { bool FileAccessUnix::file_exists(const String &p_path) {
FILE *g; int err;
//printf("opening file %s\n", p_fname.c_str()); struct stat st;
String filename = fix_path(p_path); String filename = fix_path(p_path);
g = fopen(filename.utf8().get_data(), "rb");
if (g == NULL) {
// Does the name exist at all?
err = stat(filename.utf8().get_data(), &st);
if (err)
return false; return false;
} else {
fclose(g); #ifdef UNIX_ENABLED
// See if we have access to the file
if (access(filename.utf8().get_data(), F_OK))
return false;
#else
if (_access(filename.utf8().get_data(), 4) == -1)
return false;
#endif
// See if this is a regular file
switch (st.st_mode & S_IFMT) {
case S_IFLNK:
case S_IFREG:
return true; return true;
default:
return false;
} }
} }
@ -225,9 +266,9 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
String file = fix_path(p_file); String file = fix_path(p_file);
struct stat flags; struct stat flags;
bool success = (stat(file.utf8().get_data(), &flags) == 0); int err = stat(file.utf8().get_data(), &flags);
if (success) { if (!err) {
return flags.st_mtime; return flags.st_mtime;
} else { } else {
print_line("ERROR IN: " + p_file); print_line("ERROR IN: " + p_file);
@ -249,6 +290,7 @@ FileAccessUnix::FileAccessUnix() {
flags = 0; flags = 0;
last_error = OK; last_error = OK;
} }
FileAccessUnix::~FileAccessUnix() { FileAccessUnix::~FileAccessUnix() {
close(); close();