parent
8c306bde67
commit
280fc59edf
|
@ -469,7 +469,7 @@ class Plugin : public Libc::Plugin
|
||||||
if ((flags & O_EXCL) == O_EXCL)
|
if ((flags & O_EXCL) == O_EXCL)
|
||||||
ffat_flags |= FA_CREATE_NEW;
|
ffat_flags |= FA_CREATE_NEW;
|
||||||
else
|
else
|
||||||
ffat_flags |= FA_CREATE_ALWAYS;
|
ffat_flags |= FA_OPEN_ALWAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
FRESULT res = f_open(&ffat_file, pathname, ffat_flags);
|
FRESULT res = f_open(&ffat_file, pathname, ffat_flags);
|
||||||
|
|
|
@ -499,16 +499,34 @@ class Plugin : public Libc::Plugin
|
||||||
* Open directory that contains the file to be opened/created
|
* Open directory that contains the file to be opened/created
|
||||||
*/
|
*/
|
||||||
File_system::Dir_handle const dir_handle =
|
File_system::Dir_handle const dir_handle =
|
||||||
file_system()->dir(dir_path, false);
|
file_system()->dir(dir_path, false);
|
||||||
|
|
||||||
Node_handle_guard guard(dir_handle);
|
Node_handle_guard guard(dir_handle);
|
||||||
|
|
||||||
|
File_system::File_handle handle;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open or create file
|
* Open or create file
|
||||||
*/
|
*/
|
||||||
bool const create = (flags & O_CREAT) != 0;
|
bool const create = (flags & O_CREAT) != 0;
|
||||||
File_system::File_handle const handle =
|
|
||||||
file_system()->file(dir_handle, basename, mode, create);
|
bool opened = false;
|
||||||
|
while (!opened) {
|
||||||
|
try {
|
||||||
|
handle = file_system()->file(dir_handle, basename, mode, create);
|
||||||
|
opened = true;
|
||||||
|
} catch (File_system::Node_already_exists) {
|
||||||
|
if (flags & O_EXCL)
|
||||||
|
throw File_system::Node_already_exists();
|
||||||
|
/* try to open the existing file */
|
||||||
|
try {
|
||||||
|
handle = file_system()->file(dir_handle, basename, mode, false);
|
||||||
|
opened = true;
|
||||||
|
} catch (File_system::Lookup_failed) {
|
||||||
|
/* the file got deleted in the meantime */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Plugin_context *context = new (Genode::env()->heap())
|
Plugin_context *context = new (Genode::env()->heap())
|
||||||
Plugin_context(handle);
|
Plugin_context(handle);
|
||||||
|
|
|
@ -277,7 +277,7 @@ namespace File_system {
|
||||||
throw Permission_denied();
|
throw Permission_denied();
|
||||||
|
|
||||||
if (create)
|
if (create)
|
||||||
ffat_flags |= FA_CREATE_ALWAYS; /* overwrite existing file */
|
ffat_flags |= FA_CREATE_NEW;
|
||||||
|
|
||||||
if ((mode == READ_ONLY) || (mode == READ_WRITE))
|
if ((mode == READ_ONLY) || (mode == READ_WRITE))
|
||||||
ffat_flags |= FA_READ;
|
ffat_flags |= FA_READ;
|
||||||
|
|
|
@ -73,6 +73,10 @@ int main(int argc, char *argv[])
|
||||||
CALL_AND_CHECK(count, write(fd, pattern, pattern_size), (size_t)count == pattern_size, "");
|
CALL_AND_CHECK(count, write(fd, pattern, pattern_size), (size_t)count == pattern_size, "");
|
||||||
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
||||||
|
|
||||||
|
/* open the file with O_CREAT again (should have no effect on the file) */
|
||||||
|
CALL_AND_CHECK(fd, open(file_name, O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", file_name);
|
||||||
|
CALL_AND_CHECK(ret, close(fd), ret == 0, "");
|
||||||
|
|
||||||
/* query file status of new file */
|
/* query file status of new file */
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
CALL_AND_CHECK(ret, stat(file_name, &stat_buf), ret == 0, "file_name=%s", file_name);
|
CALL_AND_CHECK(ret, stat(file_name, &stat_buf), ret == 0, "file_name=%s", file_name);
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace Noux {
|
||||||
OPEN_MODE_WRONLY = 1,
|
OPEN_MODE_WRONLY = 1,
|
||||||
OPEN_MODE_RDWR = 2,
|
OPEN_MODE_RDWR = 2,
|
||||||
OPEN_MODE_ACCMODE = 3,
|
OPEN_MODE_ACCMODE = 3,
|
||||||
OPEN_MODE_CREATE = 0x0200,
|
OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -275,7 +275,8 @@ namespace Noux {
|
||||||
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
||||||
enum Fchdir_error { FCHDIR_ERR_NOT_DIR = NUM_GENERAL_ERRORS };
|
enum Fchdir_error { FCHDIR_ERR_NOT_DIR = NUM_GENERAL_ERRORS };
|
||||||
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = NUM_GENERAL_ERRORS };
|
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = NUM_GENERAL_ERRORS };
|
||||||
enum Open_error { OPEN_ERR_UNACCESSIBLE, OPEN_ERR_NO_PERM };
|
enum Open_error { OPEN_ERR_UNACCESSIBLE, OPEN_ERR_NO_PERM,
|
||||||
|
OPEN_ERR_EXISTS };
|
||||||
enum Execve_error { EXECVE_NONEXISTENT = NUM_GENERAL_ERRORS };
|
enum Execve_error { EXECVE_NONEXISTENT = NUM_GENERAL_ERRORS };
|
||||||
enum Unlink_error { UNLINK_ERR_NO_ENTRY, UNLINK_ERR_NO_PERM };
|
enum Unlink_error { UNLINK_ERR_NO_ENTRY, UNLINK_ERR_NO_PERM };
|
||||||
enum Rename_error { RENAME_ERR_NO_ENTRY, RENAME_ERR_CROSS_FS,
|
enum Rename_error { RENAME_ERR_NO_ENTRY, RENAME_ERR_CROSS_FS,
|
||||||
|
|
|
@ -607,19 +607,37 @@ namespace {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & O_CREAT)
|
bool opened = false;
|
||||||
unlink(pathname);
|
while (!opened) {
|
||||||
|
Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path));
|
||||||
Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path));
|
sysio()->open_in.mode = flags;
|
||||||
sysio()->open_in.mode = flags;
|
if (noux()->syscall(Noux::Session::SYSCALL_OPEN))
|
||||||
|
opened = true;
|
||||||
if (!noux()->syscall(Noux::Session::SYSCALL_OPEN)) {
|
else
|
||||||
/*
|
switch (sysio()->error.open) {
|
||||||
* XXX we should return meaningful errno values
|
case Noux::Sysio::OPEN_ERR_UNACCESSIBLE:
|
||||||
*/
|
if (!(flags & O_CREAT)) {
|
||||||
PDBG("ENOENT (sysio()->error.open=%d)", sysio()->error.open);
|
errno = ENOENT;
|
||||||
errno = ENOENT;
|
return 0;
|
||||||
return 0;
|
}
|
||||||
|
/* O_CREAT is set, so try to create the file */
|
||||||
|
Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path));
|
||||||
|
sysio()->open_in.mode = flags | O_EXCL;
|
||||||
|
if (noux()->syscall(Noux::Session::SYSCALL_OPEN))
|
||||||
|
opened = true;
|
||||||
|
else
|
||||||
|
switch (sysio()->error.open) {
|
||||||
|
case Noux::Sysio::OPEN_ERR_EXISTS:
|
||||||
|
/* file has been created by someone else in the meantime */
|
||||||
|
break;
|
||||||
|
case Noux::Sysio::OPEN_ERR_NO_PERM: errno = EPERM; return 0;
|
||||||
|
default: errno = ENOENT; return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Noux::Sysio::OPEN_ERR_NO_PERM: errno = EPERM; return 0;
|
||||||
|
case Noux::Sysio::OPEN_ERR_EXISTS: errno = EEXIST; return 0;
|
||||||
|
default: errno = ENOENT; return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Libc::Plugin_context *context = noux_context(sysio()->open_out.fd);
|
Libc::Plugin_context *context = noux_context(sysio()->open_out.fd);
|
||||||
|
|
|
@ -416,7 +416,10 @@ namespace Noux {
|
||||||
error = Sysio::OPEN_ERR_NO_PERM; }
|
error = Sysio::OPEN_ERR_NO_PERM; }
|
||||||
catch (::File_system::Invalid_handle) {
|
catch (::File_system::Invalid_handle) {
|
||||||
error = Sysio::OPEN_ERR_NO_PERM; }
|
error = Sysio::OPEN_ERR_NO_PERM; }
|
||||||
catch (::File_system::Lookup_failed) { }
|
catch (::File_system::Lookup_failed) {
|
||||||
|
error = Sysio::OPEN_ERR_UNACCESSIBLE; }
|
||||||
|
catch (::File_system::Node_already_exists) {
|
||||||
|
error = Sysio::OPEN_ERR_EXISTS; }
|
||||||
|
|
||||||
sysio->error.open = error;
|
sysio->error.open = error;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user