From 0d4c16e0c08ba45ee32177fae63fdeb5b71b52a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 5 Mar 2006 18:11:59 +0000 Subject: [PATCH] * Reduced the stack usage of most of the I/O paths - there were several places that put one or more full paths on the stack before, which could cause some problems under certain conditions. * Cleaned up KPath, ie. use size_t instead of int32 where appropriate, added license. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16585 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/fs/KPath.h | 70 +++--- src/system/kernel/fs/KPath.cpp | 149 ++++++------ src/system/kernel/fs/vfs.cpp | 388 +++++++++++++++++------------- 3 files changed, 334 insertions(+), 273 deletions(-) diff --git a/headers/private/kernel/fs/KPath.h b/headers/private/kernel/fs/KPath.h index 889f9eeb50..e1d2215139 100644 --- a/headers/private/kernel/fs/KPath.h +++ b/headers/private/kernel/fs/KPath.h @@ -1,56 +1,58 @@ -// KPath.h -// -// A simple class wrapping a path. Has a fixed-sized buffer. - +/* + * Copyright 2004-2006, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ #ifndef _K_PATH_H #define _K_PATH_H + #include + namespace BPrivate { namespace DiskDevice { class KPath { -public: - KPath(int32 bufferSize = B_PATH_NAME_LENGTH); - KPath(const char* path, bool normalize = false, - int32 bufferSize = B_PATH_NAME_LENGTH); - KPath(const KPath& other); - ~KPath(); + public: + KPath(size_t bufferSize = B_PATH_NAME_LENGTH); + KPath(const char* path, bool normalize = false, + size_t bufferSize = B_PATH_NAME_LENGTH); + KPath(const KPath& other); + ~KPath(); - status_t SetTo(const char *path, bool normalize = false, - int32 bufferSize = B_PATH_NAME_LENGTH); + status_t SetTo(const char *path, bool normalize = false, + size_t bufferSize = B_PATH_NAME_LENGTH); - status_t InitCheck() const; + status_t InitCheck() const; - status_t SetPath(const char *path, bool normalize = false); - const char *Path() const; - int32 Length() const; + status_t SetPath(const char *path, bool normalize = false); + const char *Path() const; + size_t Length() const { return fPathLength; } - int32 BufferSize() const; - char *LockBuffer(); - void UnlockBuffer(); + size_t BufferSize() const { return fBufferSize; } + char *LockBuffer(); + void UnlockBuffer(); - const char *Leaf() const; - status_t ReplaceLeaf(const char *newLeaf); + const char *Leaf() const; + status_t ReplaceLeaf(const char *newLeaf); - status_t Append(const char *toAppend, bool isComponent = true); + status_t Append(const char *toAppend, bool isComponent = true); - KPath& operator=(const KPath& other); - KPath& operator=(const char* path); + KPath& operator=(const KPath& other); + KPath& operator=(const char* path); - bool operator==(const KPath& other) const; - bool operator==(const char* path) const; - bool operator!=(const KPath& other) const; - bool operator!=(const char* path) const; + bool operator==(const KPath& other) const; + bool operator==(const char* path) const; + bool operator!=(const KPath& other) const; + bool operator!=(const char* path) const; -private: - void _ChopTrailingSlashes(); + private: + void _ChopTrailingSlashes(); - char* fBuffer; - int32 fBufferSize; - int32 fPathLength; - bool fLocked; + char* fBuffer; + size_t fBufferSize; + size_t fPathLength; + bool fLocked; }; } // namespace DiskDevice diff --git a/src/system/kernel/fs/KPath.cpp b/src/system/kernel/fs/KPath.cpp index dff26a73dd..ce6c006f91 100644 --- a/src/system/kernel/fs/KPath.cpp +++ b/src/system/kernel/fs/KPath.cpp @@ -1,59 +1,68 @@ -// KPath.cpp +/* + * Copyright 2004-2006, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ -#include -#include +/** A simple class wrapping a path. Has a fixed-sized buffer. */ #include #include #include -// debugging -#define DBG(x) -//#define DBG(x) x -#define OUT dprintf +#include +#include -// constructor -KPath::KPath(int32 bufferSize) - : fBuffer(NULL), - fBufferSize(0), - fPathLength(0), - fLocked(false) + +// debugging +#define TRACE(x) ; +//#define TRACE(x) dprintf x + + +KPath::KPath(size_t bufferSize) + : + fBuffer(NULL), + fBufferSize(0), + fPathLength(0), + fLocked(false) { SetTo(NULL, bufferSize); } -// constructor -KPath::KPath(const char* path, bool normalize, int32 bufferSize) - : fBuffer(NULL), - fBufferSize(0), - fPathLength(0), - fLocked(false) + +KPath::KPath(const char* path, bool normalize, size_t bufferSize) + : + fBuffer(NULL), + fBufferSize(0), + fPathLength(0), + fLocked(false) { SetTo(path, normalize, bufferSize); } -// copy constructor + KPath::KPath(const KPath& other) - : fBuffer(NULL), - fBufferSize(0), - fPathLength(0), - fLocked(false) + : + fBuffer(NULL), + fBufferSize(0), + fPathLength(0), + fLocked(false) { *this = other; } -// destructor + KPath::~KPath() { free(fBuffer); } -// SetTo + status_t -KPath::SetTo(const char* path, bool normalize, int32 bufferSize) +KPath::SetTo(const char* path, bool normalize, size_t bufferSize) { - if (bufferSize <= 0) + if (bufferSize == 0) bufferSize = B_PATH_NAME_LENGTH; + // free the previous buffer, if the buffer size differs if (fBuffer && fBufferSize != bufferSize) { free(fBuffer); @@ -62,6 +71,7 @@ KPath::SetTo(const char* path, bool normalize, int32 bufferSize) } fPathLength = 0; fLocked = false; + // allocate buffer if (!fBuffer) fBuffer = (char*)malloc(bufferSize); @@ -74,19 +84,20 @@ KPath::SetTo(const char* path, bool normalize, int32 bufferSize) return SetPath(path, normalize); } -// InitCheck + status_t KPath::InitCheck() const { - return (fBuffer ? B_OK : B_NO_MEMORY); + return fBuffer ? B_OK : B_NO_MEMORY; } -// SetPath + status_t KPath::SetPath(const char *path, bool normalize) { if (!fBuffer) return B_NO_INIT; + if (path) { if (normalize) { // normalize path @@ -99,11 +110,12 @@ KPath::SetPath(const char *path, bool normalize) fPathLength = strlen(fBuffer); } else { // don't normalize path - int32 len = strlen(path); - if (len >= fBufferSize) + size_t length = strlen(path); + if (length >= fBufferSize) return B_BUFFER_OVERFLOW; - memcpy(fBuffer, path, len + 1); - fPathLength = len; + + memcpy(fBuffer, path, length + 1); + fPathLength = length; _ChopTrailingSlashes(); } } else { @@ -113,61 +125,49 @@ KPath::SetPath(const char *path, bool normalize) return B_OK; } -// Path + const char* KPath::Path() const { return fBuffer; } -// Length -int32 -KPath::Length() const -{ - return fPathLength; -} -// BufferSize -int32 -KPath::BufferSize() const -{ - return fBufferSize; -} - -// LockBuffer char * KPath::LockBuffer() { if (!fBuffer || fLocked) return NULL; + fLocked = true; return fBuffer; } -// UnlockBuffer + void KPath::UnlockBuffer() { if (!fLocked) { - DBG(OUT("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n")); + TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n")); return; } fLocked = false; fPathLength = strnlen(fBuffer, fBufferSize); if (fPathLength == fBufferSize) { - DBG(OUT("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n")); + TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n")); fPathLength--; fBuffer[fPathLength] = '\0'; } _ChopTrailingSlashes(); } -// Leaf + const char * KPath::Leaf() const { if (!fBuffer) return NULL; + // only "/" has trailing slashes -- then we have to return the complete // buffer, as we have to do in case there are no slashes at all if (fPathLength != 1 || fBuffer[0] != '/') { @@ -179,13 +179,14 @@ KPath::Leaf() const return fBuffer; } -// ReplaceLeaf + status_t KPath::ReplaceLeaf(const char *newLeaf) { const char *leaf = Leaf(); if (!leaf) return B_NO_INIT; + int32 leafIndex = leaf - fBuffer; // chop off the current leaf (don't replace "/", though) if (leafIndex != 0 || fBuffer[leafIndex - 1]) { @@ -193,13 +194,14 @@ KPath::ReplaceLeaf(const char *newLeaf) fPathLength = leafIndex; _ChopTrailingSlashes(); } + // if a leaf was given, append it if (newLeaf) return Append(newLeaf); return B_OK; } -// Append + status_t KPath::Append(const char *component, bool isComponent) { @@ -210,26 +212,29 @@ KPath::Append(const char *component, bool isComponent) return B_BAD_VALUE; if (fPathLength == 0) return SetPath(component); + // get component length - int32 componentLen = strlen(component); - if (componentLen < 1) + size_t componentLength = strlen(component); + if (componentLength < 1) return B_OK; + // if our current path is empty, we just copy the supplied one // compute the result path len bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/' && component[0] != '/'; - int32 resultPathLen = fPathLength + componentLen + (insertSlash ? 1 : 0); - if (resultPathLen >= fBufferSize) + size_t resultPathLength = fPathLength + componentLength + (insertSlash ? 1 : 0); + if (resultPathLength >= fBufferSize) return B_BUFFER_OVERFLOW; + // compose the result path if (insertSlash) fBuffer[fPathLength++] = '/'; - memcpy(fBuffer + fPathLength, component, componentLen + 1); - fPathLength = resultPathLen; + memcpy(fBuffer + fPathLength, component, componentLength + 1); + fPathLength = resultPathLength; return B_OK; } -// = + KPath& KPath::operator=(const KPath& other) { @@ -237,7 +242,7 @@ KPath::operator=(const KPath& other) return *this; } -// = + KPath& KPath::operator=(const char* path) { @@ -245,41 +250,43 @@ KPath::operator=(const char* path) return *this; } -// == + bool KPath::operator==(const KPath& other) const { if (!fBuffer) - return (!other.fBuffer); + return !other.fBuffer; + return (other.fBuffer && fPathLength == other.fPathLength && strcmp(fBuffer, other.fBuffer) == 0); } -// == + bool KPath::operator==(const char* path) const { if (!fBuffer) return (!path); - return (path && strcmp(fBuffer, path) == 0); + + return path && !strcmp(fBuffer, path); } -// != + bool KPath::operator!=(const KPath& other) const { return !(*this == other); } -// != + bool KPath::operator!=(const char* path) const { return !(*this == path); } -// _ChopTrailingSlashes + void KPath::_ChopTrailingSlashes() { diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index cb6c14257d..b9b8bc6f3e 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -1703,16 +1703,20 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize) { FUNCTION(("dir_vnode_to_path(%p, %p, %lu)\n", vnode, buffer, bufferSize)); + if (vnode == NULL || buffer == NULL) + return B_BAD_VALUE; + /* this implementation is currently bound to B_PATH_NAME_LENGTH */ - char path[B_PATH_NAME_LENGTH]; - int32 insert = sizeof(path); + KPath pathBuffer; + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + int32 insert = pathBuffer.BufferSize(); int32 maxLevel = 256; int32 length; status_t status; - if (vnode == NULL || buffer == NULL) - return EINVAL; - // we don't use get_vnode() here because this call is more // efficient and does all we need from get_vnode() inc_vnode_ref_count(vnode); @@ -1735,7 +1739,8 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize) int type; // lookup the parent vnode - status = FS_CALL(vnode, lookup)(vnode->mount->cookie, vnode->private_node, "..", &parentID, &type); + status = FS_CALL(vnode, lookup)(vnode->mount->cookie, vnode->private_node, "..", + &parentID, &type); if (status < B_OK) goto out; @@ -1744,7 +1749,8 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize) mutex_unlock(&sVnodeMutex); if (parentVnode == NULL) { - panic("dir_vnode_to_path: could not lookup vnode (mountid 0x%lx vnid 0x%Lx)\n", vnode->device, parentID); + panic("dir_vnode_to_path: could not lookup vnode (mountid 0x%lx vnid 0x%Lx)\n", + vnode->device, parentID); status = B_ENTRY_NOT_FOUND; goto out; } @@ -1761,8 +1767,10 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize) // Does the file system support getting the name of a vnode? // If so, get it here... - if (status == B_OK && FS_CALL(vnode, get_vnode_name)) - status = FS_CALL(vnode, get_vnode_name)(vnode->mount->cookie, vnode->private_node, name, B_FILE_NAME_LENGTH); + if (status == B_OK && FS_CALL(vnode, get_vnode_name)) { + status = FS_CALL(vnode, get_vnode_name)(vnode->mount->cookie, vnode->private_node, + name, B_FILE_NAME_LENGTH); + } // ... if not, find it out later (by iterating through // the parent directory, searching for the id) @@ -1795,7 +1803,8 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize) // in the parent directory now fs_cookie cookie; - status = FS_CALL(vnode, open_dir)(vnode->mount->cookie, vnode->private_node, &cookie); + status = FS_CALL(vnode, open_dir)(vnode->mount->cookie, vnode->private_node, + &cookie); if (status >= B_OK) { struct dirent *dirent = (struct dirent *)nameBuffer; while (true) { @@ -1836,7 +1845,7 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize) TRACE((" path is: %s\n", path + insert)); // copy the path to the output buffer - length = sizeof(path) - insert; + length = pathBuffer.BufferSize() - insert; if (length <= (int)bufferSize) memcpy(buffer, path + insert, length); else @@ -2488,15 +2497,17 @@ vfs_get_vnode_from_fd(int fd, bool kernel, void **vnode) extern "C" status_t vfs_get_vnode_from_path(const char *path, bool kernel, void **_vnode) { - struct vnode *vnode; - status_t status; - char buffer[B_PATH_NAME_LENGTH + 1]; - TRACE(("vfs_get_vnode_from_path: entry. path = '%s', kernel %d\n", path, kernel)); - strlcpy(buffer, path, sizeof(buffer)); + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - status = path_to_vnode(buffer, true, &vnode, NULL, kernel); + char *buffer = pathBuffer.LockBuffer(); + strlcpy(buffer, path, pathBuffer.BufferSize()); + + struct vnode *vnode; + status_t status = path_to_vnode(buffer, true, &vnode, NULL, kernel); if (status < B_OK) return status; @@ -2561,14 +2572,18 @@ vfs_lookup_vnode(mount_id mountID, vnode_id vnodeID, void **_vnode) extern "C" status_t vfs_get_fs_node_from_path(mount_id mountID, const char *path, bool kernel, void **_node) { - char buffer[B_PATH_NAME_LENGTH + 1]; + TRACE(("vfs_get_fs_node_from_path(mountID = %ld, path = \"%s\", kernel %d)\n", + mountID, path, kernel)); + + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *buffer = pathBuffer.LockBuffer(); + strlcpy(buffer, path, pathBuffer.BufferSize()); + struct vnode *vnode; - status_t status; - - TRACE(("vfs_get_fs_node_from_path(mountID = %ld, path = \"%s\", kernel %d)\n", mountID, path, kernel)); - - strlcpy(buffer, path, sizeof(buffer)); - status = path_to_vnode(buffer, true, &vnode, NULL, kernel); + status_t status = path_to_vnode(buffer, true, &vnode, NULL, kernel); if (status < B_OK) return status; @@ -2704,7 +2719,11 @@ vfs_normalize_path(const char *path, char *buffer, size_t bufferSize, TRACE(("vfs_normalize_path(`%s')\n", path)); // copy the supplied path to the stack, so it can be modified - char mutablePath[B_PATH_NAME_LENGTH + 1]; + KPath mutablePathBuffer(B_PATH_NAME_LENGTH + 1); + if (mutablePathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *mutablePath = mutablePathBuffer.LockBuffer(); if (strlcpy(mutablePath, path, B_PATH_NAME_LENGTH) >= B_PATH_NAME_LENGTH) return B_NAME_TOO_LONG; @@ -2723,7 +2742,8 @@ vfs_normalize_path(const char *path, char *buffer, size_t bufferSize, if (isDir) error = vnode_path_to_vnode(dirNode, leaf, false, 0, &dirNode, NULL, NULL); if (error != B_OK) { - TRACE(("vfs_normalize_path(): failed to get dir vnode for \".\" or \"..\": %s\n", strerror(error))); + TRACE(("vfs_normalize_path(): failed to get dir vnode for \".\" or \"..\": %s\n", + strerror(error))); return error; } @@ -6372,7 +6392,10 @@ status_t _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf, char *userPath, size_t pathLength) { - char path[B_PATH_NAME_LENGTH + 1]; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + struct vnode *vnode; status_t status; @@ -6408,8 +6431,10 @@ _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf, if (status < B_OK) return status; + char *path = pathBuffer.LockBuffer(); + // get the directory path - status = dir_vnode_to_path(vnode, path, sizeof(path)); + status = dir_vnode_to_path(vnode, path, pathBuffer.BufferSize()); put_vnode(vnode); // we don't need the vnode anymore if (status < B_OK) @@ -6418,8 +6443,9 @@ _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf, // append the leaf name if (leaf) { // insert a directory separator if this is not the file system root - if ((strcmp(path, "/") && strlcat(path, "/", sizeof(path)) >= sizeof(path)) - || strlcat(path, leaf, sizeof(path)) >= sizeof(path)) { + if ((strcmp(path, "/") && strlcat(path, "/", pathBuffer.BufferSize()) + >= pathBuffer.BufferSize()) + || strlcat(path, leaf, pathBuffer.BufferSize()) >= pathBuffer.BufferSize()) { return B_NAME_TOO_LONG; } } @@ -6429,6 +6455,7 @@ _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf, return len; if (len >= (int)pathLength) return B_BUFFER_OVERFLOW; + return B_OK; } @@ -6457,36 +6484,33 @@ _user_open_entry_ref(dev_t device, ino_t inode, const char *userName, int _user_open(int fd, const char *userPath, int openMode, int perms) { - char path[B_PATH_NAME_LENGTH + 1]; - int status; + KPath path(B_PATH_NAME_LENGTH + 1); + if (path.InitCheck() != B_OK) + return B_NO_MEMORY; - if (!IS_USER_ADDRESS(userPath)) + char *buffer = path.LockBuffer(); + + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(buffer, userPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - if (openMode & O_CREAT) - return file_create(fd, path, openMode, perms, false); + return file_create(fd, buffer, openMode, perms, false); - return file_open(fd, path, openMode, false); + return file_open(fd, buffer, openMode, false); } int -_user_open_dir_entry_ref(dev_t device, ino_t inode, const char *uname) +_user_open_dir_entry_ref(dev_t device, ino_t inode, const char *userName) { - if (uname) { + if (userName != NULL) { char name[B_FILE_NAME_LENGTH]; - if (!IS_USER_ADDRESS(uname)) + if (!IS_USER_ADDRESS(userName) + || user_strlcpy(name, userName, sizeof(name)) < B_OK) return B_BAD_ADDRESS; - int status = user_strlcpy(name, uname, sizeof(name)); - if (status < B_OK) - return status; - return dir_open_entry_ref(device, inode, name, false); } return dir_open_entry_ref(device, inode, NULL, false); @@ -6496,17 +6520,17 @@ _user_open_dir_entry_ref(dev_t device, ino_t inode, const char *uname) int _user_open_dir(int fd, const char *userPath) { - char path[B_PATH_NAME_LENGTH + 1]; - int status; + KPath path(B_PATH_NAME_LENGTH + 1); + if (path.InitCheck() != B_OK) + return B_NO_MEMORY; - if (!IS_USER_ADDRESS(userPath)) + char *buffer = path.LockBuffer(); + + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(buffer, userPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - return dir_open(fd, path, false); + return dir_open(fd, buffer, false); } @@ -6618,16 +6642,16 @@ _user_create_dir_entry_ref(dev_t device, ino_t inode, const char *userName, int status_t _user_create_dir(int fd, const char *userPath, int perms) { - char path[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - if (!IS_USER_ADDRESS(userPath)) + char *path = pathBuffer.LockBuffer(); + + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - return dir_create(fd, path, perms, false); } @@ -6635,11 +6659,17 @@ _user_create_dir(int fd, const char *userPath, int perms) status_t _user_remove_dir(int fd, const char *userPath) { - char path[B_PATH_NAME_LENGTH + 1]; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - if ((userPath != NULL && !IS_USER_ADDRESS(userPath)) - || (userPath != NULL && user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK)) - return B_BAD_ADDRESS; + char *path = pathBuffer.LockBuffer(); + + if (userPath != NULL) { + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK) + return B_BAD_ADDRESS; + } return dir_remove(fd, userPath ? path : NULL, false); } @@ -6648,28 +6678,30 @@ _user_remove_dir(int fd, const char *userPath) status_t _user_read_link(int fd, const char *userPath, char *userBuffer, size_t *userBufferSize) { - char path[B_PATH_NAME_LENGTH + 1]; - char buffer[B_PATH_NAME_LENGTH]; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1), linkBuffer; + if (pathBuffer.InitCheck() != B_OK || linkBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + size_t bufferSize; - status_t status; if (!IS_USER_ADDRESS(userBuffer) || !IS_USER_ADDRESS(userBufferSize) || user_memcpy(&bufferSize, userBufferSize, sizeof(size_t)) < B_OK) return B_BAD_ADDRESS; - if (userPath) { - if (!IS_USER_ADDRESS(userPath)) - return B_BAD_ADDRESS; + char *path = pathBuffer.LockBuffer(); + char *buffer = linkBuffer.LockBuffer(); - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; + if (userPath) { + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK) + return B_BAD_ADDRESS; if (bufferSize > B_PATH_NAME_LENGTH) bufferSize = B_PATH_NAME_LENGTH; } - status = common_read_link(fd, userPath ? path : NULL, buffer, &bufferSize, false); + status_t status = common_read_link(fd, userPath ? path : NULL, buffer, + &bufferSize, false); // we also update the bufferSize in case of errors // (the real length will be returned in case of B_BUFFER_OVERFLOW) @@ -6689,23 +6721,21 @@ _user_read_link(int fd, const char *userPath, char *userBuffer, size_t *userBuff status_t _user_write_link(const char *userPath, const char *userToPath) { - char path[B_PATH_NAME_LENGTH + 1]; - char toPath[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + KPath toPathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK || toPathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + char *toPath = toPathBuffer.LockBuffer(); if (!IS_USER_ADDRESS(userPath) - || !IS_USER_ADDRESS(userToPath)) + || !IS_USER_ADDRESS(userToPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK + || user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = check_path(toPath); + status_t status = check_path(toPath); if (status < B_OK) return status; @@ -6717,23 +6747,21 @@ status_t _user_create_symlink(int fd, const char *userPath, const char *userToPath, int mode) { - char path[B_PATH_NAME_LENGTH + 1]; - char toPath[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + KPath toPathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK || toPathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + char *toPath = toPathBuffer.LockBuffer(); if (!IS_USER_ADDRESS(userPath) - || !IS_USER_ADDRESS(userToPath)) + || !IS_USER_ADDRESS(userToPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK + || user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = check_path(toPath); + status_t status = check_path(toPath); if (status < B_OK) return status; @@ -6744,23 +6772,21 @@ _user_create_symlink(int fd, const char *userPath, const char *userToPath, status_t _user_create_link(const char *userPath, const char *userToPath) { - char path[B_PATH_NAME_LENGTH + 1]; - char toPath[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + KPath toPathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK || toPathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + char *toPath = toPathBuffer.LockBuffer(); if (!IS_USER_ADDRESS(userPath) - || !IS_USER_ADDRESS(userToPath)) + || !IS_USER_ADDRESS(userToPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK + || user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = user_strlcpy(toPath, userToPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = check_path(toPath); + status_t status = check_path(toPath); if (status < B_OK) return status; @@ -6771,16 +6797,16 @@ _user_create_link(const char *userPath, const char *userToPath) status_t _user_unlink(int fd, const char *userPath) { - char path[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - if (!IS_USER_ADDRESS(userPath)) + char *path = pathBuffer.LockBuffer(); + + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - return common_unlink(fd, path, false); } @@ -6789,21 +6815,19 @@ status_t _user_rename(int oldFD, const char *userOldPath, int newFD, const char *userNewPath) { - char oldPath[B_PATH_NAME_LENGTH + 1]; - char newPath[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath oldPathBuffer(B_PATH_NAME_LENGTH + 1); + KPath newPathBuffer(B_PATH_NAME_LENGTH + 1); + if (oldPathBuffer.InitCheck() != B_OK || newPathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - if (!IS_USER_ADDRESS(userOldPath) || !IS_USER_ADDRESS(userNewPath)) + char *oldPath = oldPathBuffer.LockBuffer(); + char *newPath = newPathBuffer.LockBuffer(); + + if (!IS_USER_ADDRESS(userOldPath) || !IS_USER_ADDRESS(userNewPath) + || user_strlcpy(oldPath, userOldPath, B_PATH_NAME_LENGTH) < B_OK + || user_strlcpy(newPath, userNewPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(oldPath, userOldPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - - status = user_strlcpy(newPath, userNewPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - return common_rename(oldFD, oldPath, newFD, newPath, false); } @@ -6811,16 +6835,16 @@ _user_rename(int oldFD, const char *userOldPath, int newFD, status_t _user_access(const char *userPath, int mode) { - char path[B_PATH_NAME_LENGTH + 1]; - status_t status; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; - if (!IS_USER_ADDRESS(userPath)) + char *path = pathBuffer.LockBuffer(); + + if (!IS_USER_ADDRESS(userPath) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; - status = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (status < 0) - return status; - return common_access(path, mode, false); } @@ -6840,13 +6864,19 @@ _user_read_stat(int fd, const char *userPath, bool traverseLink, if (userPath) { // path given: get the stat of the node referred to by (fd, path) - char path[B_PATH_NAME_LENGTH + 1]; if (!IS_USER_ADDRESS(userPath)) return B_BAD_ADDRESS; - int len = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (len < 0) - return len; - if (len >= B_PATH_NAME_LENGTH) + + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + + ssize_t length = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); + if (length < B_OK) + return length; + if (length >= B_PATH_NAME_LENGTH) return B_NAME_TOO_LONG; status = common_path_read_stat(fd, path, traverseLink, &stat, false); @@ -6876,12 +6906,11 @@ status_t _user_write_stat(int fd, const char *userPath, bool traverseLeafLink, const struct stat *userStat, size_t statSize, int statMask) { - char path[B_PATH_NAME_LENGTH + 1]; - struct stat stat; - if (statSize > sizeof(struct stat)) return B_BAD_VALUE; + struct stat stat; + if (!IS_USER_ADDRESS(userStat) || user_memcpy(&stat, userStat, statSize) < B_OK) return B_BAD_ADDRESS; @@ -6896,10 +6925,17 @@ _user_write_stat(int fd, const char *userPath, bool traverseLeafLink, // path given: write the stat of the node referred to by (fd, path) if (!IS_USER_ADDRESS(userPath)) return B_BAD_ADDRESS; - int len = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); - if (len < 0) - return len; - if (len >= B_PATH_NAME_LENGTH) + + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + + ssize_t length = user_strlcpy(path, userPath, B_PATH_NAME_LENGTH); + if (length < B_OK) + return length; + if (length >= B_PATH_NAME_LENGTH) return B_NAME_TOO_LONG; status = common_path_write_stat(fd, path, traverseLeafLink, &stat, @@ -6926,15 +6962,19 @@ _user_write_stat(int fd, const char *userPath, bool traverseLeafLink, int _user_open_attr_dir(int fd, const char *userPath) { - char pathBuffer[B_PATH_NAME_LENGTH + 1]; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); if (userPath != NULL) { if (!IS_USER_ADDRESS(userPath) - || user_strlcpy(pathBuffer, userPath, B_PATH_NAME_LENGTH) < B_OK) + || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; } - return attr_dir_open(fd, userPath ? pathBuffer : NULL, false); + return attr_dir_open(fd, userPath ? path : NULL, false); } @@ -6980,13 +7020,18 @@ _user_remove_attr(int fd, const char *userName) status_t _user_rename_attr(int fromFile, const char *userFromName, int toFile, const char *userToName) { - char fromName[B_FILE_NAME_LENGTH]; - char toName[B_FILE_NAME_LENGTH]; - if (!IS_USER_ADDRESS(userFromName) || !IS_USER_ADDRESS(userToName)) return B_BAD_ADDRESS; + KPath fromNameBuffer(B_FILE_NAME_LENGTH); + KPath toNameBuffer(B_FILE_NAME_LENGTH); + if (fromNameBuffer.InitCheck() != B_OK || toNameBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *fromName = fromNameBuffer.LockBuffer(); + char *toName = toNameBuffer.LockBuffer(); + if (user_strlcpy(fromName, userFromName, B_FILE_NAME_LENGTH) < B_OK || user_strlcpy(toName, userToName, B_FILE_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; @@ -7053,23 +7098,26 @@ _user_remove_index(dev_t device, const char *userName) status_t _user_getcwd(char *userBuffer, size_t size) { - char buffer[B_PATH_NAME_LENGTH]; - status_t status; - - TRACE(("user_getcwd: buf %p, %ld\n", userBuffer, size)); - if (!IS_USER_ADDRESS(userBuffer)) return B_BAD_ADDRESS; + KPath pathBuffer(B_PATH_NAME_LENGTH + 1); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + TRACE(("user_getcwd: buf %p, %ld\n", userBuffer, size)); + if (size > B_PATH_NAME_LENGTH) size = B_PATH_NAME_LENGTH; - status = get_cwd(buffer, size, false); - if (status < 0) + char *path = pathBuffer.LockBuffer(); + + status_t status = get_cwd(path, size, false); + if (status < B_OK) return status; // Copy back the result - if (user_strlcpy(userBuffer, buffer, size) < B_OK) + if (user_strlcpy(userBuffer, path, size) < B_OK) return B_BAD_ADDRESS; return status; @@ -7079,10 +7127,14 @@ _user_getcwd(char *userBuffer, size_t size) status_t _user_setcwd(int fd, const char *userPath) { - char path[B_PATH_NAME_LENGTH]; - TRACE(("user_setcwd: path = %p\n", userPath)); + KPath pathBuffer(B_PATH_NAME_LENGTH); + if (pathBuffer.InitCheck() != B_OK) + return B_NO_MEMORY; + + char *path = pathBuffer.LockBuffer(); + if (userPath != NULL) { if (!IS_USER_ADDRESS(userPath) || user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK)