int ioctl_sem_open(struct ipc_driver *drv, unsigned long arg) { int error = 0; struct ipc_create_t ipc_param; if(copy_from_user(&ipc_param, (void *)arg, sizeof(struct ipc_create_t))) { err_msg(err_trace, "%s(): Error in copy_from_user()\n", __FUNCTION__); error = -EFAULT; goto do_exit; } ipc_param.handle = ipc_sem_create( drv, &ipc_param ); if(!ipc_param.handle) { err_msg(err_trace, "%s(): Error in ipc_sem_create()\n", __FUNCTION__); error = -EINVAL; goto do_exit; } if(copy_to_user((void*)arg, (void*)&ipc_param, sizeof(struct ipc_create_t))) { err_msg(err_trace, "%s(): Error in copy_to_user()\n", __FUNCTION__); error = -EFAULT; goto do_exit; } do_exit: return error; }
ipc_t ipc_create(const char* name, int owner) { int isInited = 0; struct Queue* queue; ipc_t conn = malloc(sizeof(struct ipc_t)); sprintf(conn->name, "/arqvenger_%s", name); if ((conn->lock = sem_open(conn->name, O_CREAT | O_EXCL, 0666, 0)) == SEM_FAILED) { conn->lock = sem_open(conn->name, 0); if (conn->lock == SEM_FAILED) { print_errno("Failed adquiring named lock"); return NULL; } sem_wait(conn->lock); isInited = 1; } conn->fd = shm_open(conn->name, O_CREAT | O_RDWR, 0666); if (conn->fd == -1) { print_errno("shm_open failed"); sem_close(conn->lock); if (owner) { sem_unlink(conn->name); } free(conn); return NULL; } if (!isInited) { if (ftruncate(conn->fd, SHMEM_SIZE) == -1) { print_errno("Truncate failed"); sem_close(conn->lock); if (owner) { sem_unlink(conn->name); shm_unlink(conn->name); } free(conn); return NULL; } } conn->queue = mmap(NULL, SHMEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, conn->fd, 0); if (conn->queue == (void*) -1) { print_errno("mmap"); sem_close(conn->lock); if (owner) { sem_unlink(conn->name); shm_unlink(conn->name); } free(conn); return NULL; } if (isInited) { sem_post(conn->lock); return conn; } queue = conn->queue; for (size_t i = 0; i < ENTRIES_PER_QUEUE; i++) { queue->index[i] = -1; queue->slots[i].len = 0; } queue->readWait = ipc_sem_create(0); queue->writeSem = ipc_sem_create(ENTRIES_PER_QUEUE); if (queue->readWait == -1 || queue->writeSem == -1) { print_errno("failed creating sems"); sem_close(conn->lock); ipc_sem_destroy(queue->readWait); ipc_sem_destroy(queue->writeSem); munmap(conn->queue, SHMEM_SIZE); if (owner) { sem_unlink(conn->name); shm_unlink(conn->name); } free(conn); return NULL; } sem_post(conn->lock); return conn; }