* dir_vnode_to_path() now uses B_* error codes instead of POSIX ones, and also
returns the correct error code if the buffer was too small (should be ERANGE instead of ENOBUF). * Also, it is now independent of B_PATH_NAME_LENGTH, and therefore should fulfill POSIX getcwd() requirements. This should also close ticket #3352. * Is there any reason to allocate another buffer instead of using memmove() at the end instead of memcpy()? git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34276 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d52f7d5214
commit
432bb91f34
@ -112,6 +112,10 @@ const static uint32 kMaxUnusedVnodes = 8192;
|
||||
const static uint32 kMaxEntryCacheEntryCount = 8192;
|
||||
// Maximum number of entries per entry cache. It's a hard limit ATM.
|
||||
|
||||
const static size_t kMaxPathLength = 65536;
|
||||
// The absolute maximum path length (for getcwd() - this is not depending
|
||||
// on PATH_MAX
|
||||
|
||||
struct EntryCacheKey {
|
||||
EntryCacheKey(ino_t dirID, const char* name)
|
||||
:
|
||||
@ -2624,14 +2628,13 @@ 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)
|
||||
if (vnode == NULL || buffer == NULL || bufferSize == 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!S_ISDIR(vnode->type))
|
||||
return B_NOT_A_DIRECTORY;
|
||||
|
||||
/* this implementation is currently bound to B_PATH_NAME_LENGTH */
|
||||
KPath pathBuffer;
|
||||
KPath pathBuffer(bufferSize);
|
||||
if (pathBuffer.InitCheck() != B_OK)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@ -2657,6 +2660,7 @@ dir_vnode_to_path(struct vnode* vnode, char* buffer, size_t bufferSize,
|
||||
}
|
||||
|
||||
path[--insert] = '\0';
|
||||
// the path is filled right to left
|
||||
|
||||
while (true) {
|
||||
// the name buffer is also used for fs_read_dir()
|
||||
@ -2707,12 +2711,12 @@ dir_vnode_to_path(struct vnode* vnode, char* buffer, size_t bufferSize,
|
||||
break;
|
||||
}
|
||||
|
||||
// ToDo: add an explicit check for loops in about 10 levels to do
|
||||
// TODO: add an explicit check for loops in about 10 levels to do
|
||||
// real loop detection
|
||||
|
||||
// don't go deeper as 'maxLevel' to prevent circular loops
|
||||
if (maxLevel-- < 0) {
|
||||
status = ELOOP;
|
||||
status = B_LINK_LIMIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2721,7 +2725,7 @@ dir_vnode_to_path(struct vnode* vnode, char* buffer, size_t bufferSize,
|
||||
length = strlen(name);
|
||||
insert -= length;
|
||||
if (insert <= 0) {
|
||||
status = ENOBUFS;
|
||||
status = B_RESULT_NOT_REPRESENTABLE;
|
||||
goto out;
|
||||
}
|
||||
memcpy(path + insert, name, length);
|
||||
@ -2739,7 +2743,7 @@ dir_vnode_to_path(struct vnode* vnode, char* buffer, size_t bufferSize,
|
||||
if (length <= (int)bufferSize)
|
||||
memcpy(buffer, path + insert, length);
|
||||
else
|
||||
status = ENOBUFS;
|
||||
status = B_RESULT_NOT_REPRESENTABLE;
|
||||
|
||||
out:
|
||||
put_vnode(vnode);
|
||||
@ -9354,18 +9358,20 @@ _user_remove_index(dev_t device, const char* userName)
|
||||
status_t
|
||||
_user_getcwd(char* userBuffer, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return B_BAD_VALUE;
|
||||
if (!IS_USER_ADDRESS(userBuffer))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
KPath pathBuffer(B_PATH_NAME_LENGTH + 1);
|
||||
if (size > kMaxPathLength)
|
||||
size = kMaxPathLength;
|
||||
|
||||
KPath pathBuffer(size);
|
||||
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;
|
||||
|
||||
char* path = pathBuffer.LockBuffer();
|
||||
|
||||
status_t status = get_cwd(path, size, false);
|
||||
|
Loading…
Reference in New Issue
Block a user