Cleaned up the _get_port_info() and _get_next_port_info() calls, factored

out the port_info setup to fill_port_info(), implemented the B_CURRENT_TEAM
behaviour as described in the BeBook (well, almost, since B_CURRENT_TEAM
is not defined in R5, it's just "0"), improved error checking.
Cleaned up user syscalls.
Replaced SYS_MAX_OS_NAME_LEN with B_OS_NAME_LENGTH.
Banned strncpy().
Added our license.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6687 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-02-23 04:02:24 +00:00
parent 31bedae9ea
commit 70f0602f2d
+126 -149
View File
@@ -1,4 +1,10 @@
/* ports for IPC */ /* ports for IPC */
/*
** Copyright 2002-2004, The OpenBeOS Team. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/* /*
** Copyright 2001, Mark-Jan Bastian. All rights reserved. ** Copyright 2001, Mark-Jan Bastian. All rights reserved.
** Distributed under the terms of the NewOS License. ** Distributed under the terms of the NewOS License.
@@ -189,7 +195,7 @@ create_port(int32 queue_length, const char *name)
name = "unnamed port"; name = "unnamed port";
name_len = strlen(name) + 1; name_len = strlen(name) + 1;
name_len = min(name_len, SYS_MAX_OS_NAME_LEN); name_len = min(name_len, B_OS_NAME_LENGTH);
temp_name = (char *)malloc(name_len); temp_name = (char *)malloc(name_len);
if (temp_name == NULL) if (temp_name == NULL)
return ENOMEM; return ENOMEM;
@@ -404,17 +410,32 @@ find_port(const char *port_name)
} }
/** Fills the port_info structure with information from the specified
* port.
* The port lock must be held when called.
*/
static void
fill_port_info(struct port_entry *port, port_info *info, size_t size)
{
info->port = port->id;
info->team = port->owner;
info->capacity = port->capacity;
info->total_count = ports->total_count;
strlcpy(info->name, ports->name, B_OS_NAME_LENGTH);
get_sem_count(port->read_sem, &info->queue_count);
}
status_t status_t
_get_port_info(port_id id, port_info *info, size_t size) _get_port_info(port_id id, port_info *info, size_t size)
{ {
int slot; int slot;
int state; int state;
if (ports_active == false) if (info == NULL || size != sizeof(port_info))
return B_BAD_PORT_ID; return B_BAD_VALUE;
if (info == NULL) if (!ports_active || id < 0)
return EINVAL;
if (id < 0)
return B_BAD_PORT_ID; return B_BAD_PORT_ID;
slot = id % MAX_PORTS; slot = id % MAX_PORTS;
@@ -430,63 +451,49 @@ _get_port_info(port_id id, port_info *info, size_t size)
} }
// fill a port_info struct with info // fill a port_info struct with info
info->port = ports[slot].id; fill_port_info(&ports[slot], info, size);
// info->owner = ports[slot].owner;
strncpy(info->name, ports[slot].name, min(strlen(ports[slot].name),SYS_MAX_OS_NAME_LEN-1));
info->capacity = ports[slot].capacity;
get_sem_count(ports[slot].read_sem, &info->queue_count);
info->total_count = ports[slot].total_count;
RELEASE_PORT_LOCK(ports[slot]); RELEASE_PORT_LOCK(ports[slot]);
restore_interrupts(state); restore_interrupts(state);
// from our port_entry return B_OK;
return B_NO_ERROR;
} }
status_t status_t
_get_next_port_info(team_id team, int32 *cookie, struct port_info *info, size_t size) _get_next_port_info(team_id team, int32 *_cookie, struct port_info *info, size_t size)
{ {
int state; int state;
int slot; int slot;
if (ports_active == false)
return B_BAD_PORT_ID;
if (cookie == NULL)
return B_BAD_VALUE;
if (*cookie == 0) { if (info == NULL || size != sizeof(port_info) || _cookie == NULL || team < B_OK)
// return first found return B_BAD_VALUE;
slot = 0; if (!ports_active)
} else { return B_BAD_PORT_ID;
// start at index cookie, but check cookie against MAX_PORTS
slot = *cookie; slot = *_cookie;
if (slot >= MAX_PORTS) if (slot >= MAX_PORTS)
return B_BAD_PORT_ID; return B_BAD_PORT_ID;
}
if (team == B_CURRENT_TEAM)
team = team_get_current_team_id();
info->port = -1; // used as found flag
// spinlock // spinlock
state = disable_interrupts(); state = disable_interrupts();
GRAB_PORT_LIST_LOCK(); GRAB_PORT_LIST_LOCK();
info->port = -1; // used as found flag
while (slot < MAX_PORTS) { while (slot < MAX_PORTS) {
GRAB_PORT_LOCK(ports[slot]); GRAB_PORT_LOCK(ports[slot]);
if (ports[slot].id != -1) if (ports[slot].id != -1 && ports[slot].owner == team) {
if (ports[slot].owner == team) { // found one!
// found one! fill_port_info(&ports[slot], info, size);
// copy the info
info->port = ports[slot].id; RELEASE_PORT_LOCK(ports[slot]);
// info->owner = ports[slot].owner; slot++;
strncpy(info->name, ports[slot].name, min(strlen(ports[slot].name),SYS_MAX_OS_NAME_LEN-1)); break;
info->capacity = ports[slot].capacity; }
get_sem_count(ports[slot].read_sem, &info->queue_count);
info->total_count = ports[slot].total_count;
RELEASE_PORT_LOCK(ports[slot]);
slot++;
break;
}
RELEASE_PORT_LOCK(ports[slot]); RELEASE_PORT_LOCK(ports[slot]);
slot++; slot++;
} }
@@ -495,7 +502,8 @@ _get_next_port_info(team_id team, int32 *cookie, struct port_info *info, size_t
if (info->port == -1) if (info->port == -1)
return B_BAD_PORT_ID; return B_BAD_PORT_ID;
*cookie = slot;
*_cookie = slot;
return B_NO_ERROR; return B_NO_ERROR;
} }
@@ -516,9 +524,7 @@ port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout)
int len; int len;
int state; int state;
if (ports_active == false) if (!ports_active || id < 0)
return B_BAD_PORT_ID;
if (id < 0)
return B_BAD_PORT_ID; return B_BAD_PORT_ID;
slot = id % MAX_PORTS; slot = id % MAX_PORTS;
@@ -555,7 +561,7 @@ port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout)
} }
// once message arrived, read data's length // once message arrived, read data's length
// determine tail // determine tail
// read data's head length // read data's head length
t = ports[slot].head; t = ports[slot].head;
@@ -1039,24 +1045,18 @@ port_test_thread_func(void *arg)
port_id port_id
user_create_port(int32 queue_length, const char *uname) user_create_port(int32 queueLength, const char *userName)
{ {
if(uname != NULL) { char name[B_OS_NAME_LENGTH];
char name[SYS_MAX_OS_NAME_LEN];
status_t rc;
if((addr)uname >= KERNEL_BASE && (addr)uname <= KERNEL_TOP) if (userName == NULL)
return ERR_VM_BAD_USER_MEMORY; return create_port(queueLength, NULL);
rc = user_strncpy(name, uname, SYS_MAX_OS_NAME_LEN-1); if (!IS_USER_ADDRESS(userName)
if(rc < 0) || user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK)
return rc; return B_BAD_ADDRESS;
name[SYS_MAX_OS_NAME_LEN-1] = 0;
return create_port(queue_length, name); return create_port(queueLength, name);
} else {
return create_port(queue_length, NULL);
}
} }
@@ -1075,79 +1075,62 @@ user_delete_port(port_id id)
port_id port_id
user_find_port(const char *port_name) user_find_port(const char *userName)
{ {
if (port_name != NULL) { char name[B_OS_NAME_LENGTH];
char name[SYS_MAX_OS_NAME_LEN];
status_t rc;
if((addr)port_name >= KERNEL_BASE && (addr)port_name <= KERNEL_TOP) if (userName == NULL)
return ERR_VM_BAD_USER_MEMORY; return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userName)
|| user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK)
return B_BAD_ADDRESS;
rc = user_strncpy(name, port_name, SYS_MAX_OS_NAME_LEN-1); return find_port(name);
if(rc < 0)
return rc;
name[SYS_MAX_OS_NAME_LEN-1] = 0;
return find_port(name);
} else {
return EINVAL;
}
} }
status_t status_t
user_get_port_info(port_id id, struct port_info *uinfo) user_get_port_info(port_id id, struct port_info *userInfo)
{ {
status_t res; struct port_info info;
struct port_info info; status_t status;
status_t rc;
if (uinfo == NULL) if (userInfo == NULL)
return EINVAL; return B_BAD_VALUE;
if ((addr)uinfo >= KERNEL_BASE && (addr)uinfo <= KERNEL_TOP) if (!IS_USER_ADDRESS(userInfo))
return ERR_VM_BAD_USER_MEMORY; return B_BAD_ADDRESS;
res = get_port_info(id, &info); status = get_port_info(id, &info);
// copy to userspace
rc = user_memcpy(uinfo, &info, sizeof(struct port_info)); // copy back to user space
if (rc < 0) if (status == B_OK && user_memcpy(userInfo, &info, sizeof(struct port_info)) < B_OK)
return rc; return B_BAD_ADDRESS;
return res;
return status;
} }
status_t status_t
user_get_next_port_info(team_id uteam, int32 *ucookie, struct port_info *uinfo) user_get_next_port_info(team_id team, int32 *userCookie, struct port_info *userInfo)
{ {
status_t res; struct port_info info;
struct port_info info; status_t status;
int32 cookie; int32 cookie;
status_t rc;
if (ucookie == NULL) if (userCookie == NULL || userInfo == NULL)
return EINVAL; return B_BAD_VALUE;
if (uinfo == NULL) if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo)
return EINVAL; || user_memcpy(&cookie, userCookie, sizeof(int32)) < B_OK)
if ((addr)ucookie >= KERNEL_BASE && (addr)ucookie <= KERNEL_TOP) return B_BAD_ADDRESS;
return ERR_VM_BAD_USER_MEMORY;
if ((addr)uinfo >= KERNEL_BASE && (addr)uinfo <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
// copy from userspace status = get_next_port_info(team, &cookie, &info);
rc = user_memcpy(&cookie, ucookie, sizeof(int32));
if (rc < 0) // copy back to user space
return rc; if (user_memcpy(userCookie, &cookie, sizeof(int32)) < B_OK
|| (status == B_OK && user_memcpy(userInfo, &info, sizeof(struct port_info)) < B_OK))
res = get_next_port_info(uteam, &cookie, &info); return B_BAD_ADDRESS;
// copy to userspace
rc = user_memcpy(ucookie, &cookie, sizeof(int32)); return status;
if (rc < 0)
return rc;
rc = user_memcpy(uinfo, &info, sizeof(struct port_info));
if (rc < 0)
return rc;
return res;
} }
@@ -1166,31 +1149,24 @@ user_port_count(port_id port)
status_t status_t
user_read_port_etc(port_id uport, int32 *umsg_code, void *umsg_buffer, user_read_port_etc(port_id port, int32 *userCode, void *userBuffer,
size_t ubuffer_size, uint32 uflags, bigtime_t utimeout) size_t bufferSize, uint32 flags, bigtime_t timeout)
{ {
ssize_t res; int32 messageCode;
int32 msg_code; ssize_t status;
status_t rc;
if (umsg_code == NULL)
return EINVAL;
if (umsg_buffer == NULL)
return EINVAL;
if((addr)umsg_code >= KERNEL_BASE && (addr)umsg_code <= KERNEL_TOP) if (userCode == NULL || userBuffer == NULL)
return ERR_VM_BAD_USER_MEMORY; return B_BAD_VALUE;
if((addr)umsg_buffer >= KERNEL_BASE && (addr)umsg_buffer <= KERNEL_TOP) if (!IS_USER_ADDRESS(userCode) || !IS_USER_ADDRESS(userBuffer))
return ERR_VM_BAD_USER_MEMORY; return B_BAD_ADDRESS;
res = read_port_etc(uport, &msg_code, umsg_buffer, ubuffer_size, status = read_port_etc(port, &messageCode, userBuffer, bufferSize,
uflags | PORT_FLAG_USE_USER_MEMCPY | B_CAN_INTERRUPT, utimeout); flags | PORT_FLAG_USE_USER_MEMCPY | B_CAN_INTERRUPT, timeout);
rc = user_memcpy(umsg_code, &msg_code, sizeof(int32)); if (status == B_OK && user_memcpy(userCode, &messageCode, sizeof(int32)) < B_OK)
if(rc < 0) return B_BAD_ADDRESS;
return rc;
return res; return status;
} }
@@ -1202,14 +1178,15 @@ user_set_port_owner(port_id port, team_id team)
status_t status_t
user_write_port_etc(port_id uport, int32 umsg_code, void *umsg_buffer, user_write_port_etc(port_id port, int32 messageCode, void *userBuffer,
size_t ubuffer_size, uint32 uflags, bigtime_t utimeout) size_t bufferSize, uint32 flags, bigtime_t timeout)
{ {
if (umsg_buffer == NULL) if (userBuffer == NULL)
return EINVAL; return B_BAD_VALUE;
if((addr)umsg_buffer >= KERNEL_BASE && (addr)umsg_buffer <= KERNEL_TOP) if (!IS_USER_ADDRESS(userBuffer))
return ERR_VM_BAD_USER_MEMORY; return B_BAD_ADDRESS;
return write_port_etc(uport, umsg_code, umsg_buffer, ubuffer_size,
uflags | PORT_FLAG_USE_USER_MEMCPY | B_CAN_INTERRUPT, utimeout); return write_port_etc(port, messageCode, userBuffer, bufferSize,
flags | PORT_FLAG_USE_USER_MEMCPY | B_CAN_INTERRUPT, timeout);
} }