diff --git a/headers/private/storage/kernel_interface.h b/headers/private/storage/kernel_interface.h index 91088f9505..6418f10625 100644 --- a/headers/private/storage/kernel_interface.h +++ b/headers/private/storage/kernel_interface.h @@ -68,11 +68,25 @@ status_t stat_dev(dev_t dev, fs_info* info); it doesn't already exist). */ status_t open(const char *path, OpenFlags flags, FileDescriptor &result); -/*! \brief Same as the other version of open() except the file is created with the +/*! \brief Same as the first version, but tries to open read-only, if + first the attempt failed with B_READ_ONLY_DEVICE or + B_PERMISSION_DENIED and \a fallBackToReadOnly is \c true. +*/ +status_t open(const char *path, OpenFlags flags, FileDescriptor &result, + bool fallBackToReadOnly); + +/*! \brief Same as the first version of open() except the file is created with the permissions given by creationFlags if it doesn't exist. */ status_t open(const char *path, OpenFlags flags, CreationFlags creationFlags, FileDescriptor &result); +/*! \brief Same as the third version, but tries to open read-only, if + first the attempt failed with B_READ_ONLY_DEVICE or + B_PERMISSION_DENIED and \a fallBackToReadOnly is \c true. +*/ +status_t open(const char *path, OpenFlags flags, CreationFlags creationFlags, + FileDescriptor &result, bool fallBackToReadOnly); + /*! \brief Closes a previously open()ed file. */ status_t close( FileDescriptor file ); diff --git a/src/kits/storage/Directory.cpp b/src/kits/storage/Directory.cpp index 0a47eed191..8735abe5a6 100644 --- a/src/kits/storage/Directory.cpp +++ b/src/kits/storage/Directory.cpp @@ -249,7 +249,7 @@ BDirectory::SetTo(const char *path) // open_dir() does always traverse those. Therefore we open the FD for // BNode (without the O_NOTRAVERSE flag). BPrivate::Storage::FileDescriptor fd = BPrivate::Storage::NullFd; - result = BPrivate::Storage::open(path, O_RDWR, fd); + result = BPrivate::Storage::open(path, O_RDWR, fd, true); if (result == B_OK) { result = set_fd(fd); if (result != B_OK) diff --git a/src/kits/storage/Node.cpp b/src/kits/storage/Node.cpp index dd8ba25240..30f2b0c1fe 100644 --- a/src/kits/storage/Node.cpp +++ b/src/kits/storage/Node.cpp @@ -247,8 +247,10 @@ status_t BNode::SetTo(const char *path) { Unset(); - if (path != NULL) - fCStatus = BPrivate::Storage::open(path, O_RDWR | O_NOTRAVERSE, fFd); + if (path != NULL) { + fCStatus = BPrivate::Storage::open(path, O_RDWR | O_NOTRAVERSE, fFd, + true); + } return fCStatus; } diff --git a/src/kits/storage/kernel_interface.POSIX.cpp b/src/kits/storage/kernel_interface.POSIX.cpp index 3ba16744c4..9baccdef97 100644 --- a/src/kits/storage/kernel_interface.POSIX.cpp +++ b/src/kits/storage/kernel_interface.POSIX.cpp @@ -67,6 +67,19 @@ BPrivate::Storage::open( const char *path, OpenFlags flags, FileDescriptor &resu return (result == -1) ? errno : B_OK ; } +status_t +BPrivate::Storage::open( const char *path, OpenFlags flags, + FileDescriptor &result, bool fallBackToReadOnly ) +{ + status_t error = open(path, flags, result); + if (error == B_READ_ONLY_DEVICE || error == B_PERMISSION_DENIED + && fallBackToReadOnly && (flags & O_RWMASK == O_RDWR)) { + flags = flags & ~O_RWMASK | O_RDONLY; + error = open(path, flags, result); + } + return error; +} + /*! Same as the other version of open() except the file is created with the permissions given by creationFlags if it doesn't exist. */ status_t @@ -83,6 +96,20 @@ BPrivate::Storage::open( const char *path, OpenFlags flags, return (result == -1) ? errno : B_OK ; } +status_t +BPrivate::Storage::open( const char *path, OpenFlags flags, + CreationFlags creationFlags, FileDescriptor &result, + bool fallBackToReadOnly ) +{ + status_t error = open(path, flags, creationFlags, result); + if (error == B_READ_ONLY_DEVICE || error == B_PERMISSION_DENIED + && fallBackToReadOnly && (flags & O_RWMASK == O_RDWR)) { + flags = flags & ~O_RWMASK | O_RDONLY; + error = open(path, flags, creationFlags, result); + } + return error; +} + status_t BPrivate::Storage::close(BPrivate::Storage::FileDescriptor file) {