* 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:
Axel Dörfler 2009-11-26 14:18:23 +00:00
parent aec945c959
commit 00362625b9

View File

@ -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
// to do it)
if (S_ISLNK(nextVnode->type)
&& !(!traverseLeafLink && nextPath[0] == '\0')) {
&& (traverseLeafLink || nextPath[0] != '\0')) {
size_t bufferSize;
char* buffer;
@ -5025,6 +5025,7 @@ static int
create_vnode(struct vnode* directory, const char* name, int openMode,
int perms, bool kernel)
{
bool traverse = ((openMode & (O_NOTRAVERSE | O_NOFOLLOW)) == 0);
status_t status = B_ERROR;
struct vnode* vnode;
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
// 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()
// 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
// 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
// O_NOTRAVERSE is set.
if (S_ISLNK(vnode->type) && (openMode & O_NOTRAVERSE) == 0) {
if (S_ISLNK(vnode->type) && traverse) {
putter.Put();
char clonedName[B_FILE_NAME_LENGTH + 1];
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);
}
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);
// on success keep the vnode reference for the FD
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",
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
struct vnode* vnode;
@ -5238,6 +5244,11 @@ file_open_entry_ref(dev_t mountID, ino_t directoryID, const char* name,
if (status != B_OK)
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);
if (fd < 0)
put_vnode(vnode);
@ -5251,7 +5262,7 @@ file_open_entry_ref(dev_t mountID, ino_t directoryID, const char* name,
static int
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",
fd, path, openMode, kernel));
@ -5264,6 +5275,11 @@ file_open(int fd, char* path, int openMode, bool kernel)
if (status != B_OK)
return status;
if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->type)) {
put_vnode(vnode);
return B_LINK_LIMIT;
}
// open the vnode
int newFD = open_vnode(vnode, openMode, kernel);
// put only on error -- otherwise our reference was transferred to the FD