int sys_shmget(struct proc *p, void *v, register_t *retval) { struct sys_shmget_args /* { syscallarg(key_t) key; syscallarg(size_t) size; syscallarg(int) shmflg; } */ *uap = v; int segnum, mode, error; mode = SCARG(uap, shmflg) & ACCESSPERMS; if (SCARG(uap, key) != IPC_PRIVATE) { again: segnum = shm_find_segment_by_key(SCARG(uap, key)); if (segnum >= 0) return (shmget_existing(p, uap, mode, segnum, retval)); if ((SCARG(uap, shmflg) & IPC_CREAT) == 0) return (ENOENT); } error = shmget_allocate_segment(p, uap, mode, retval); if (error == EAGAIN) goto again; return (error); }
/* Handle a shmget() request. */ int handle_shmget(pid_t pid, struct shmget_msg *shmget_msg, struct cmsgcred *cred ) { int segnum, mode, error; struct shmid_ds *shmseg; struct shm_handle *handle; //if (!jail_sysvipc_allowed && td->td_cmsgcred->cr_prison != NULL) // return (ENOSYS); mode = shmget_msg->shmflg & ACCESSPERMS; sysvd_print("ask for key = %ld\n", shmget_msg->key); shmget_msg->key = (shmget_msg->key & 0x3FFF) | (shmget_msg->type << 30); sysvd_print("ask for key = %ld\n", shmget_msg->key); if (shmget_msg->key != IPC_PRIVATE) { //again: segnum = shm_find_segment_by_key(shmget_msg->key); if (segnum >= 0) { error = shmget_existing(shmget_msg, mode, segnum, cred); //TODO if daemon is multithreading //if (error == EAGAIN) // goto again; goto done; } if ((shmget_msg->shmflg & IPC_CREAT) == 0) { error = -ENOENT; goto done_err; } } error = shmget_allocate_segment(pid, shmget_msg, mode, cred); sysvd_print("allocate segment = %d\n", error); done: /* * Install to th client the file corresponding to the * shared memory segment. * client_fd is the file descriptor added in the client * files table. */ shmseg = shm_find_segment_by_shmid(error); if (shmseg == NULL) { sysvd_print_err("can not find segment by shmid\n"); return (-1); } handle = (struct shm_handle *)shmseg->shm_internal; if (install_fd_client(pid, handle->fd) != 0) error = errno; done_err: return (error); }