* Added support for O_NOFOLLOW.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34279 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
aec945c959
commit
00362625b9
@ -2264,7 +2264,7 @@ vnode_path_to_vnode(struct vnode* vnode, char* path, bool traverseLeafLink,
|
|||||||
// If the new node is a symbolic link, resolve it (if we've been told
|
// If the new node is a symbolic link, resolve it (if we've been told
|
||||||
// to do it)
|
// to do it)
|
||||||
if (S_ISLNK(nextVnode->type)
|
if (S_ISLNK(nextVnode->type)
|
||||||
&& !(!traverseLeafLink && nextPath[0] == '\0')) {
|
&& (traverseLeafLink || nextPath[0] != '\0')) {
|
||||||
size_t bufferSize;
|
size_t bufferSize;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
|
|
||||||
@ -5025,6 +5025,7 @@ static int
|
|||||||
create_vnode(struct vnode* directory, const char* name, int openMode,
|
create_vnode(struct vnode* directory, const char* name, int openMode,
|
||||||
int perms, bool kernel)
|
int perms, bool kernel)
|
||||||
{
|
{
|
||||||
|
bool traverse = ((openMode & (O_NOTRAVERSE | O_NOFOLLOW)) == 0);
|
||||||
status_t status = B_ERROR;
|
status_t status = B_ERROR;
|
||||||
struct vnode* vnode;
|
struct vnode* vnode;
|
||||||
void* cookie;
|
void* cookie;
|
||||||
@ -5035,7 +5036,7 @@ create_vnode(struct vnode* directory, const char* name, int openMode,
|
|||||||
// node the entry refers to. So we can actually never call the create() hook
|
// node the entry refers to. So we can actually never call the create() hook
|
||||||
// without O_EXCL. Instead we try to look the entry up first. If it already
|
// without O_EXCL. Instead we try to look the entry up first. If it already
|
||||||
// exists, we just open the node (unless O_EXCL), otherwise we call create()
|
// exists, we just open the node (unless O_EXCL), otherwise we call create()
|
||||||
// with O_EXCL. This introduces a race condition, since we someone else
|
// with O_EXCL. This introduces a race condition, since someone else
|
||||||
// might have created the entry in the meantime. We hope the respective
|
// might have created the entry in the meantime. We hope the respective
|
||||||
// FS returns the correct error code and retry (up to 3 times) again.
|
// FS returns the correct error code and retry (up to 3 times) again.
|
||||||
|
|
||||||
@ -5050,7 +5051,7 @@ create_vnode(struct vnode* directory, const char* name, int openMode,
|
|||||||
|
|
||||||
// If the node is a symlink, we have to follow it, unless
|
// If the node is a symlink, we have to follow it, unless
|
||||||
// O_NOTRAVERSE is set.
|
// O_NOTRAVERSE is set.
|
||||||
if (S_ISLNK(vnode->type) && (openMode & O_NOTRAVERSE) == 0) {
|
if (S_ISLNK(vnode->type) && traverse) {
|
||||||
putter.Put();
|
putter.Put();
|
||||||
char clonedName[B_FILE_NAME_LENGTH + 1];
|
char clonedName[B_FILE_NAME_LENGTH + 1];
|
||||||
if (strlcpy(clonedName, name, B_FILE_NAME_LENGTH)
|
if (strlcpy(clonedName, name, B_FILE_NAME_LENGTH)
|
||||||
@ -5067,6 +5068,11 @@ create_vnode(struct vnode* directory, const char* name, int openMode,
|
|||||||
putter.SetTo(vnode);
|
putter.SetTo(vnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->type)) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return B_LINK_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
int fd = open_vnode(vnode, openMode & ~O_CREAT, kernel);
|
int fd = open_vnode(vnode, openMode & ~O_CREAT, kernel);
|
||||||
// on success keep the vnode reference for the FD
|
// on success keep the vnode reference for the FD
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
@ -5229,7 +5235,7 @@ file_open_entry_ref(dev_t mountID, ino_t directoryID, const char* name,
|
|||||||
FUNCTION(("file_open_entry_ref(ref = (%ld, %Ld, %s), openMode = %d)\n",
|
FUNCTION(("file_open_entry_ref(ref = (%ld, %Ld, %s), openMode = %d)\n",
|
||||||
mountID, directoryID, name, openMode));
|
mountID, directoryID, name, openMode));
|
||||||
|
|
||||||
bool traverse = ((openMode & O_NOTRAVERSE) == 0);
|
bool traverse = ((openMode & (O_NOTRAVERSE | O_NOFOLLOW)) == 0);
|
||||||
|
|
||||||
// get the vnode matching the entry_ref
|
// get the vnode matching the entry_ref
|
||||||
struct vnode* vnode;
|
struct vnode* vnode;
|
||||||
@ -5238,6 +5244,11 @@ file_open_entry_ref(dev_t mountID, ino_t directoryID, const char* name,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->type)) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return B_LINK_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
int fd = open_vnode(vnode, openMode, kernel);
|
int fd = open_vnode(vnode, openMode, kernel);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
put_vnode(vnode);
|
put_vnode(vnode);
|
||||||
@ -5251,7 +5262,7 @@ file_open_entry_ref(dev_t mountID, ino_t directoryID, const char* name,
|
|||||||
static int
|
static int
|
||||||
file_open(int fd, char* path, int openMode, bool kernel)
|
file_open(int fd, char* path, int openMode, bool kernel)
|
||||||
{
|
{
|
||||||
bool traverse = ((openMode & O_NOTRAVERSE) == 0);
|
bool traverse = ((openMode & (O_NOTRAVERSE | O_NOFOLLOW)) == 0);
|
||||||
|
|
||||||
FUNCTION(("file_open: fd: %d, entry path = '%s', omode %d, kernel %d\n",
|
FUNCTION(("file_open: fd: %d, entry path = '%s', omode %d, kernel %d\n",
|
||||||
fd, path, openMode, kernel));
|
fd, path, openMode, kernel));
|
||||||
@ -5264,6 +5275,11 @@ file_open(int fd, char* path, int openMode, bool kernel)
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->type)) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return B_LINK_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
// open the vnode
|
// open the vnode
|
||||||
int newFD = open_vnode(vnode, openMode, kernel);
|
int newFD = open_vnode(vnode, openMode, kernel);
|
||||||
// put only on error -- otherwise our reference was transferred to the FD
|
// put only on error -- otherwise our reference was transferred to the FD
|
||||||
|
Loading…
Reference in New Issue
Block a user