mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
8c306bde67
commit
280fc59edf
@ -469,7 +469,7 @@ class Plugin : public Libc::Plugin
|
||||
if ((flags & O_EXCL) == O_EXCL)
|
||||
ffat_flags |= FA_CREATE_NEW;
|
||||
else
|
||||
ffat_flags |= FA_CREATE_ALWAYS;
|
||||
ffat_flags |= FA_OPEN_ALWAYS;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
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);
|
||||
|
||||
File_system::File_handle handle;
|
||||
|
||||
/*
|
||||
* Open or create file
|
||||
*/
|
||||
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(handle);
|
||||
|
@ -277,7 +277,7 @@ namespace File_system {
|
||||
throw Permission_denied();
|
||||
|
||||
if (create)
|
||||
ffat_flags |= FA_CREATE_ALWAYS; /* overwrite existing file */
|
||||
ffat_flags |= FA_CREATE_NEW;
|
||||
|
||||
if ((mode == READ_ONLY) || (mode == READ_WRITE))
|
||||
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(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 */
|
||||
struct stat stat_buf;
|
||||
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_RDWR = 2,
|
||||
OPEN_MODE_ACCMODE = 3,
|
||||
OPEN_MODE_CREATE = 0x0200,
|
||||
OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -275,7 +275,8 @@ namespace Noux {
|
||||
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
||||
enum Fchdir_error { FCHDIR_ERR_NOT_DIR = 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 Unlink_error { UNLINK_ERR_NO_ENTRY, UNLINK_ERR_NO_PERM };
|
||||
enum Rename_error { RENAME_ERR_NO_ENTRY, RENAME_ERR_CROSS_FS,
|
||||
|
@ -607,19 +607,37 @@ namespace {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & O_CREAT)
|
||||
unlink(pathname);
|
||||
|
||||
Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path));
|
||||
sysio()->open_in.mode = flags;
|
||||
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_OPEN)) {
|
||||
/*
|
||||
* XXX we should return meaningful errno values
|
||||
*/
|
||||
PDBG("ENOENT (sysio()->error.open=%d)", sysio()->error.open);
|
||||
errno = ENOENT;
|
||||
return 0;
|
||||
bool opened = false;
|
||||
while (!opened) {
|
||||
Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path));
|
||||
sysio()->open_in.mode = flags;
|
||||
if (noux()->syscall(Noux::Session::SYSCALL_OPEN))
|
||||
opened = true;
|
||||
else
|
||||
switch (sysio()->error.open) {
|
||||
case Noux::Sysio::OPEN_ERR_UNACCESSIBLE:
|
||||
if (!(flags & O_CREAT)) {
|
||||
errno = ENOENT;
|
||||
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);
|
||||
|
@ -416,7 +416,10 @@ namespace Noux {
|
||||
error = Sysio::OPEN_ERR_NO_PERM; }
|
||||
catch (::File_system::Invalid_handle) {
|
||||
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;
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user