* Reviewed checking of empty paths and fixed some occurrences. Thanks to
mjw for the hint. Fixes bug #1516. * Changed _{kern,user}_create_symlink() to no longer check the supplied link string. BeOS seems to do that, but this is not standard conforming. The previous implementation even used the path processed by check_path(), which would potentially have appended a ".". * Some style cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22451 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0cf4ed1de6
commit
570263197e
@ -1487,25 +1487,28 @@ resolve_volume_root_to_mount_point(struct vnode *vnode)
|
||||
}
|
||||
|
||||
|
||||
/** \brief Gets the directory path and leaf name for a given path.
|
||||
*
|
||||
* The supplied \a path is transformed to refer to the directory part of
|
||||
* the entry identified by the original path, and into the buffer \a filename
|
||||
* the leaf name of the original entry is written.
|
||||
* Neither the returned path nor the leaf name can be expected to be
|
||||
* canonical.
|
||||
*
|
||||
* \param path The path to be analyzed. Must be able to store at least one
|
||||
* additional character.
|
||||
* \param filename The buffer into which the leaf name will be written.
|
||||
* Must be of size B_FILE_NAME_LENGTH at least.
|
||||
* \return \c B_OK, if everything went fine, \c B_NAME_TOO_LONG, if the leaf
|
||||
* name is longer than \c B_FILE_NAME_LENGTH.
|
||||
*/
|
||||
/*! \brief Gets the directory path and leaf name for a given path.
|
||||
|
||||
The supplied \a path is transformed to refer to the directory part of
|
||||
the entry identified by the original path, and into the buffer \a filename
|
||||
the leaf name of the original entry is written.
|
||||
Neither the returned path nor the leaf name can be expected to be
|
||||
canonical.
|
||||
|
||||
\param path The path to be analyzed. Must be able to store at least one
|
||||
additional character.
|
||||
\param filename The buffer into which the leaf name will be written.
|
||||
Must be of size B_FILE_NAME_LENGTH at least.
|
||||
\return \c B_OK, if everything went fine, \c B_NAME_TOO_LONG, if the leaf
|
||||
name is longer than \c B_FILE_NAME_LENGTH, or \c B_ENTRY_NOT_FOUND,
|
||||
if the given path name is empty.
|
||||
*/
|
||||
static status_t
|
||||
get_dir_path_and_leaf(char *path, char *filename)
|
||||
{
|
||||
if (*path == '\0')
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
char *p = strrchr(path, '/');
|
||||
// '/' are not allowed in file names!
|
||||
|
||||
@ -1537,7 +1540,8 @@ get_dir_path_and_leaf(char *path, char *filename)
|
||||
|
||||
|
||||
static status_t
|
||||
entry_ref_to_vnode(dev_t mountID, ino_t directoryID, const char *name, struct vnode **_vnode)
|
||||
entry_ref_to_vnode(dev_t mountID, ino_t directoryID, const char *name,
|
||||
struct vnode **_vnode)
|
||||
{
|
||||
char clonedName[B_FILE_NAME_LENGTH + 1];
|
||||
if (strlcpy(clonedName, name, B_FILE_NAME_LENGTH) >= B_FILE_NAME_LENGTH)
|
||||
@ -1550,18 +1554,18 @@ entry_ref_to_vnode(dev_t mountID, ino_t directoryID, const char *name, struct vn
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
return vnode_path_to_vnode(directory, clonedName, false, 0, _vnode, NULL, NULL);
|
||||
return vnode_path_to_vnode(directory, clonedName, false, 0, _vnode, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Returns the vnode for the relative path starting at the specified \a vnode.
|
||||
* \a path must not be NULL.
|
||||
* If it returns successfully, \a path contains the name of the last path
|
||||
* component.
|
||||
* Note, this reduces the ref_count of the starting \a vnode, no matter if
|
||||
* it is successful or not!
|
||||
/*! Returns the vnode for the relative path starting at the specified \a vnode.
|
||||
\a path must not be NULL.
|
||||
If it returns successfully, \a path contains the name of the last path
|
||||
component.
|
||||
Note, this reduces the ref_count of the starting \a vnode, no matter if
|
||||
it is successful or not!
|
||||
*/
|
||||
|
||||
static status_t
|
||||
vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink,
|
||||
int count, struct vnode **_vnode, ino_t *_parentID, int *_type)
|
||||
@ -1577,6 +1581,11 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink,
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if (*path == '\0') {
|
||||
put_vnode(vnode);
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
struct vnode *nextVnode;
|
||||
ino_t vnodeID;
|
||||
@ -1683,6 +1692,7 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink,
|
||||
// directory ("vnode" still points to that one).
|
||||
// Cut off all leading slashes if it's the root directory
|
||||
path = buffer;
|
||||
bool absoluteSymlink = false;
|
||||
if (path[0] == '/') {
|
||||
// we don't need the old directory anymore
|
||||
put_vnode(vnode);
|
||||
@ -1691,13 +1701,21 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink,
|
||||
;
|
||||
vnode = sRoot;
|
||||
inc_vnode_ref_count(vnode);
|
||||
}
|
||||
inc_vnode_ref_count(vnode);
|
||||
// balance the next recursion - we will decrement the ref_count
|
||||
// of the vnode, no matter if we succeeded or not
|
||||
|
||||
status = vnode_path_to_vnode(vnode, path, traverseLeafLink, count + 1,
|
||||
&nextVnode, &lastParentID, _type);
|
||||
absoluteSymlink = true;
|
||||
}
|
||||
|
||||
inc_vnode_ref_count(vnode);
|
||||
// balance the next recursion - we will decrement the
|
||||
// ref_count of the vnode, no matter if we succeeded or not
|
||||
|
||||
if (absoluteSymlink && *path == '\0') {
|
||||
// symlink was just "/"
|
||||
nextVnode = vnode;
|
||||
} else {
|
||||
status = vnode_path_to_vnode(vnode, path, traverseLeafLink,
|
||||
count + 1, &nextVnode, &lastParentID, _type);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
@ -1743,6 +1761,9 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode,
|
||||
if (!path)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (*path == '\0')
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// figure out if we need to start at root or at cwd
|
||||
if (*path == '/') {
|
||||
if (sRoot == NULL) {
|
||||
@ -1754,6 +1775,12 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode,
|
||||
;
|
||||
start = sRoot;
|
||||
inc_vnode_ref_count(start);
|
||||
|
||||
if (*path == '\0') {
|
||||
*_vnode = start;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
} else {
|
||||
struct io_context *context = get_current_io_context(kernel);
|
||||
|
||||
@ -1771,11 +1798,10 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode,
|
||||
}
|
||||
|
||||
|
||||
/** Returns the vnode in the next to last segment of the path, and returns
|
||||
* the last portion in filename.
|
||||
* The path buffer must be able to store at least one additional character.
|
||||
/*! Returns the vnode in the next to last segment of the path, and returns
|
||||
the last portion in filename.
|
||||
The path buffer must be able to store at least one additional character.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel)
|
||||
{
|
||||
@ -1787,37 +1813,38 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel
|
||||
}
|
||||
|
||||
|
||||
/** \brief Retrieves the directory vnode and the leaf name of an entry referred
|
||||
* to by a FD + path pair.
|
||||
*
|
||||
* \a path must be given in either case. \a fd might be omitted, in which
|
||||
* case \a path is either an absolute path or one relative to the current
|
||||
* directory. If both a supplied and \a path is relative it is reckoned off
|
||||
* of the directory referred to by \a fd. If \a path is absolute \a fd is
|
||||
* ignored.
|
||||
*
|
||||
* The caller has the responsibility to call put_vnode() on the returned
|
||||
* directory vnode.
|
||||
*
|
||||
* \param fd The FD. May be < 0.
|
||||
* \param path The absolute or relative path. Must not be \c NULL. The buffer
|
||||
* is modified by this function. It must have at least room for a
|
||||
* string one character longer than the path it contains.
|
||||
* \param _vnode A pointer to a variable the directory vnode shall be written
|
||||
* into.
|
||||
* \param filename A buffer of size B_FILE_NAME_LENGTH or larger into which
|
||||
* the leaf name of the specified entry will be written.
|
||||
* \param kernel \c true, if invoked from inside the kernel, \c false if
|
||||
* invoked from userland.
|
||||
* \return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
/*! \brief Retrieves the directory vnode and the leaf name of an entry referred
|
||||
to by a FD + path pair.
|
||||
|
||||
\a path must be given in either case. \a fd might be omitted, in which
|
||||
case \a path is either an absolute path or one relative to the current
|
||||
directory. If both a supplied and \a path is relative it is reckoned off
|
||||
of the directory referred to by \a fd. If \a path is absolute \a fd is
|
||||
ignored.
|
||||
|
||||
The caller has the responsibility to call put_vnode() on the returned
|
||||
directory vnode.
|
||||
|
||||
\param fd The FD. May be < 0.
|
||||
\param path The absolute or relative path. Must not be \c NULL. The buffer
|
||||
is modified by this function. It must have at least room for a
|
||||
string one character longer than the path it contains.
|
||||
\param _vnode A pointer to a variable the directory vnode shall be written
|
||||
into.
|
||||
\param filename A buffer of size B_FILE_NAME_LENGTH or larger into which
|
||||
the leaf name of the specified entry will be written.
|
||||
\param kernel \c true, if invoked from inside the kernel, \c false if
|
||||
invoked from userland.
|
||||
\return \c B_OK, if everything went fine, another error code otherwise.
|
||||
*/
|
||||
static status_t
|
||||
fd_and_path_to_dir_vnode(int fd, char *path, struct vnode **_vnode,
|
||||
char *filename, bool kernel)
|
||||
{
|
||||
if (!path)
|
||||
return B_BAD_VALUE;
|
||||
if (*path == '\0')
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
if (fd < 0)
|
||||
return path_to_dir_vnode(path, _vnode, filename, kernel);
|
||||
|
||||
@ -1829,9 +1856,8 @@ fd_and_path_to_dir_vnode(int fd, char *path, struct vnode **_vnode,
|
||||
}
|
||||
|
||||
|
||||
/** Returns a vnode's name in the d_name field of a supplied dirent buffer.
|
||||
/*! Returns a vnode's name in the d_name field of a supplied dirent buffer.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
get_vnode_name(struct vnode *vnode, struct vnode *parent, struct dirent *buffer,
|
||||
size_t bufferSize)
|
||||
@ -2049,12 +2075,11 @@ out:
|
||||
}
|
||||
|
||||
|
||||
/** Checks the length of every path component, and adds a '.'
|
||||
* if the path ends in a slash.
|
||||
* The given path buffer must be able to store at least one
|
||||
* additional character.
|
||||
/*! Checks the length of every path component, and adds a '.'
|
||||
if the path ends in a slash.
|
||||
The given path buffer must be able to store at least one
|
||||
additional character.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
check_path(char *to)
|
||||
{
|
||||
@ -2131,13 +2156,12 @@ get_vnode_from_fd(int fd, bool kernel)
|
||||
}
|
||||
|
||||
|
||||
/** Gets the vnode from an FD + path combination. If \a fd is lower than zero,
|
||||
* only the path will be considered. In this case, the \a path must not be
|
||||
* NULL.
|
||||
* If \a fd is a valid file descriptor, \a path may be NULL for directories,
|
||||
* and should be NULL for files.
|
||||
/*! Gets the vnode from an FD + path combination. If \a fd is lower than zero,
|
||||
only the path will be considered. In this case, the \a path must not be
|
||||
NULL.
|
||||
If \a fd is a valid file descriptor, \a path may be NULL for directories,
|
||||
and should be NULL for files.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
fd_and_path_to_vnode(int fd, char *path, bool traverseLeafLink,
|
||||
struct vnode **_vnode, ino_t *_parentID, bool kernel)
|
||||
@ -2145,6 +2169,9 @@ fd_and_path_to_vnode(int fd, char *path, bool traverseLeafLink,
|
||||
if (fd < 0 && !path)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (path != NULL && *path == '\0')
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
if (fd < 0 || (path != NULL && path[0] == '/')) {
|
||||
// no FD or absolute path
|
||||
return path_to_vnode(path, traverseLeafLink, _vnode, _parentID, kernel);
|
||||
@ -6256,18 +6283,11 @@ status_t
|
||||
_kern_create_symlink(int fd, const char *path, const char *toPath, int mode)
|
||||
{
|
||||
KPath pathBuffer(path, false, B_PATH_NAME_LENGTH + 1);
|
||||
KPath toPathBuffer(toPath, false, B_PATH_NAME_LENGTH + 1);
|
||||
if (pathBuffer.InitCheck() != B_OK || toPathBuffer.InitCheck() != B_OK)
|
||||
if (pathBuffer.InitCheck() != B_OK)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
char *toBuffer = toPathBuffer.LockBuffer();
|
||||
|
||||
status_t status = check_path(toBuffer);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return common_create_symlink(fd, pathBuffer.LockBuffer(),
|
||||
toBuffer, mode, true);
|
||||
toPath, mode, true);
|
||||
}
|
||||
|
||||
|
||||
@ -7097,10 +7117,6 @@ _user_create_symlink(int fd, const char *userPath, const char *userToPath,
|
||||
|| user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status_t status = check_path(toPath);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return common_create_symlink(fd, path, toPath, mode, false);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user