Exemple #1
0
int
linux_shmctl(struct proc *p, struct linux_shmctl_args *args)
{
    struct shmid_ds bsd_shmid;
    struct linux_shmid_ds linux_shmid;
    struct shmctl_args /* {
	int shmid;
	int cmd;
	struct shmid_ds *buf;
    } */ bsd_args;
    int error;
    caddr_t sg = stackgap_init();

    switch (args->arg2) {
    case LINUX_IPC_STAT:
	bsd_args.shmid = args->arg1;
	bsd_args.cmd = IPC_STAT;
	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
	if ((error = shmctl(p, &bsd_args)))
	    return error;
	if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid,
		    	    sizeof(struct shmid_ds))))
	    return error;
	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
	return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));

    case LINUX_IPC_SET:
	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
		    	    sizeof(linux_shmid))))
	    return error;
	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
		     	     sizeof(struct shmid_ds))))
	    return error;
	bsd_args.shmid = args->arg1;
	bsd_args.cmd = IPC_SET;
	return shmctl(p, &bsd_args);

    case LINUX_IPC_RMID:
	bsd_args.shmid = args->arg1;
	bsd_args.cmd = IPC_RMID;
	if (NULL == args->ptr)
	    bsd_args.buf = NULL;
	else {
	    if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 
		    		sizeof(linux_shmid))))
		return error;
	    linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
	    bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
	    if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
		     		 sizeof(struct shmid_ds))))
		return error;
	}
	return shmctl(p, &bsd_args);

    case LINUX_IPC_INFO:
    case LINUX_SHM_STAT:
    case LINUX_SHM_INFO:
    case LINUX_SHM_LOCK:
    case LINUX_SHM_UNLOCK:
    default:
	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->arg2);
	return EINVAL;
    }
}
int
linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
{
    struct l_shmid_ds linux_shmid;
	struct l_shminfo linux_shminfo;
	struct l_shm_info linux_shm_info;
	struct shmid_ds bsd_shmid;
    int error;

    switch (args->cmd & ~LINUX_IPC_64) {

	case LINUX_IPC_INFO: {
	    struct shminfo bsd_shminfo;

	    /* Perform shmctl wanting removed segments lookup */
	    error = kern_shmctl(td, args->shmid, IPC_INFO,
	        (void *)&bsd_shminfo, NULL);
	    if (error)
		return error;
	
	    bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo);

	    return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
	       &linux_shminfo, PTRIN(args->buf)));
	}

	case LINUX_SHM_INFO: {
	    struct shm_info bsd_shm_info;

	    /* Perform shmctl wanting removed segments lookup */
	    error = kern_shmctl(td, args->shmid, SHM_INFO,
	        (void *)&bsd_shm_info, NULL);
	    if (error)
		return error;

	    bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info);

	    return copyout(&linux_shm_info, PTRIN(args->buf),
	        sizeof(struct l_shm_info));
	}

	case LINUX_IPC_STAT:
	    /* Perform shmctl wanting removed segments lookup */
	    error = kern_shmctl(td, args->shmid, IPC_STAT,
	        (void *)&bsd_shmid, NULL);
	    if (error)
		return error;
		
	    bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);

	    return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
	  &linux_shmid, PTRIN(args->buf)));

    case LINUX_SHM_STAT:
	/* Perform shmctl wanting removed segments lookup */
	error = kern_shmctl(td, args->shmid, IPC_STAT,
	    (void *)&bsd_shmid, NULL);
	if (error)
		return error;
		
	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
	
	return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
	   &linux_shmid, PTRIN(args->buf)));

    case LINUX_IPC_SET:
	error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
	  &linux_shmid, PTRIN(args->buf));
	if (error)
    		return error;

	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);

	/* Perform shmctl wanting removed segments lookup */
	return kern_shmctl(td, args->shmid, IPC_SET,
	    (void *)&bsd_shmid, NULL);

    case LINUX_IPC_RMID: {
	void *buf;
		
	if (args->buf == 0)
    		buf = NULL;
	else {
    		error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
		    &linux_shmid, PTRIN(args->buf));
		if (error)
			return error;
		linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
		buf = (void *)&bsd_shmid;
	}
	return kern_shmctl(td, args->shmid, IPC_RMID, buf, NULL);
    }

    case LINUX_SHM_LOCK:
    case LINUX_SHM_UNLOCK:
    default:
	linux_msg(td, "ipc typ=%d not implemented", args->cmd & ~LINUX_IPC_64);
	return EINVAL;
    }
}