int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix)
{
+ struct shmid_ds buf;
+
dmix->semid = semget(dmix->ipc_key, DIRECT_IPC_SEMS,
IPC_CREAT | dmix->ipc_perm);
if (dmix->semid < 0)
return -errno;
+ if (dmix->ipc_gid < 0)
+ return 0;
+ if (shmctl(dmix->semid, IPC_STAT, &buf) < 0) {
+ int err = -errno;
+ snd_pcm_direct_semaphore_discard(dmix);
+ return err;
+ }
+ buf.shm_perm.gid = dmix->ipc_gid;
+ shmctl(dmix->semid, IPC_SET, &buf);
return 0;
}
}
if (buf.shm_nattch == 1) { /* we're the first user, clear the segment */
memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t));
+ if (dmix->ipc_gid >= 0) {
+ buf.shm_perm.gid = dmix->ipc_gid;
+ shmctl(dmix->shmid, IPC_SET, &buf);
+ }
return 1;
}
return 0;
snd_pcm_type_t type; /* type (dmix, dsnoop, dshare) */
key_t ipc_key; /* IPC key for semaphore and memory */
mode_t ipc_perm; /* IPC socket permissions */
+ int ipc_gid; /* IPC socket gid */
int semid; /* IPC global semaphore identification */
int shmid; /* IPC global shared memory identification */
snd_pcm_direct_share_t *shmptr; /* pointer to shared memory area */
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
+#include <grp.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size,
IPC_CREAT | dmix->ipc_perm);
err = -errno;
- if (dmix->u.dmix.shmid_sum < 0){
+ if (dmix->u.dmix.shmid_sum < 0) {
if (errno == EINVAL)
if ((tmpid = shmget(dmix->ipc_key + 1, 0, dmix->ipc_perm)) != -1)
if (!shmctl(tmpid, IPC_STAT, &buf))
goto retryshm;
return err;
}
+ if (!shmctl(dmix->u.dmix.shmid_sum, IPC_STAT, &buf)) {
+ err = -errno;
+ shm_sum_discard(dmix);
+ return err;
+ }
+ if (dmix->ipc_gid >= 0) {
+ buf.shm_perm.gid = dmix->ipc_gid;
+ shmctl(dmix->u.dmix.shmid_sum, IPC_SET, &buf);
+ }
dmix->u.dmix.sum_buffer = shmat(dmix->u.dmix.shmid_sum, 0, 0);
if (dmix->u.dmix.sum_buffer == (void *) -1) {
+ err = -errno;
shm_sum_discard(dmix);
- return -errno;
+ return err;
}
mlock(dmix->u.dmix.sum_buffer, size);
return 0;
* \param name Name of PCM
* \param ipc_key IPC key for semaphore and shared memory
* \param ipc_perm IPC permissions for semaphore and shared memory
+ * \param ipc_gid IPC group ID for semaphore and shared memory
* \param params Parameters for slave
* \param bindings Channel bindings
* \param slowptr Slow but more precise pointer updates
* changed in future.
*/
int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
- key_t ipc_key, mode_t ipc_perm,
+ key_t ipc_key, mode_t ipc_perm, int ipc_gid,
struct slave_params *params,
snd_config_t *bindings,
int slowptr,
dmix->ipc_key = ipc_key;
dmix->ipc_perm = ipc_perm;
+ dmix->ipc_gid = ipc_gid;
dmix->semid = -1;
dmix->shmid = -1;
int bsize, psize, ipc_key_add_uid = 0, slowptr = 0;
key_t ipc_key = 0;
mode_t ipc_perm = 0600;
+ int ipc_gid = -1;
int err;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
err = snd_config_get_integer(n, &key);
if (err < 0) {
SNDERR("The field ipc_key must be an integer type");
+
return err;
}
ipc_key = key;
ipc_perm = strtol(perm, &endp, 8);
continue;
}
+ if (strcmp(id, "ipc_gid") == 0) {
+ char *group;
+ char *endp;
+ err = snd_config_get_ascii(n, &group);
+ if (err < 0) {
+ SNDERR("The field ipc_gid must be a valid group");
+ return err;
+ }
+ if (isdigit(*group) == 0) {
+ struct group *grp = getgrnam(group);
+ if (grp == NULL) {
+ SNDERR("The field ipc_gid must be a valid group (create group %s)", group);
+ return -EINVAL;
+ }
+ ipc_gid = grp->gr_gid;
+ } else {
+ ipc_perm = strtol(group, &endp, 10);
+ }
+ continue;
+ }
if (strcmp(id, "ipc_key_add_uid") == 0) {
if ((err = snd_config_get_bool(n)) < 0) {
SNDERR("The field ipc_key_add_uid must be a boolean type");
params.period_size = psize;
params.buffer_size = bsize;
- err = snd_pcm_dmix_open(pcmp, name, ipc_key, ipc_perm, ¶ms, bindings, slowptr, root, sconf, stream, mode);
+ err = snd_pcm_dmix_open(pcmp, name, ipc_key, ipc_perm, ipc_gid, ¶ms, bindings, slowptr, root, sconf, stream, mode);
if (err < 0)
snd_config_delete(sconf);
return err;
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
+#include <grp.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
* \param name Name of PCM
* \param ipc_key IPC key for semaphore and shared memory
* \param ipc_perm IPC permissions for semaphore and shared memory
+ * \param ipc_gid IPC group ID for semaphore and shared memory
* \param params Parameters for slave
* \param bindings Channel bindings
* \param slowptr Slow but more precise pointer updates
* changed in future.
*/
int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
- key_t ipc_key, mode_t ipc_perm,
+ key_t ipc_key, mode_t ipc_perm, int ipc_gid,
struct slave_params *params,
snd_config_t *bindings,
int slowptr,
dshare->ipc_key = ipc_key;
dshare->ipc_perm = ipc_perm;
+ dshare->ipc_gid = ipc_gid;
dshare->semid = -1;
dshare->shmid = -1;
int bsize, psize, ipc_key_add_uid = 0, slowptr = 0;
key_t ipc_key = 0;
mode_t ipc_perm = 0600;
+ int ipc_gid = -1;
int err;
snd_config_for_each(i, next, conf) {
ipc_perm = strtol(perm, &endp, 8);
continue;
}
+ if (strcmp(id, "ipc_gid") == 0) {
+ char *group;
+ char *endp;
+ err = snd_config_get_ascii(n, &group);
+ if (err < 0) {
+ SNDERR("The field ipc_gid must be a valid group");
+ return err;
+ }
+ if (isdigit(*group) == 0) {
+ struct group *grp = getgrnam(group);
+ if (group == NULL) {
+ SNDERR("The field ipc_gid must be a valid group (create group %s)", grp);
+ return -EINVAL;
+ }
+ ipc_gid = grp->gr_gid;
+ } else {
+ ipc_perm = strtol(group, &endp, 10);
+ }
+ continue;
+ }
if (strcmp(id, "ipc_key_add_uid") == 0) {
err = snd_config_get_bool(n);
if (err < 0) {
params.period_size = psize;
params.buffer_size = bsize;
- err = snd_pcm_dshare_open(pcmp, name, ipc_key, ipc_perm, ¶ms, bindings, slowptr, root, sconf, stream, mode);
+ err = snd_pcm_dshare_open(pcmp, name, ipc_key, ipc_perm, ipc_gid, ¶ms, bindings, slowptr, root, sconf, stream, mode);
if (err < 0)
snd_config_delete(sconf);
return err;
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
+#include <grp.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
* \param name Name of PCM
* \param ipc_key IPC key for semaphore and shared memory
* \param ipc_perm IPC permissions for semaphore and shared memory
+ * \param ipc_gid IPC group ID for semaphore and shared memory
* \param params Parameters for slave
* \param bindings Channel bindings
* \param slowptr Slow but more precise pointer updates
* changed in future.
*/
int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
- key_t ipc_key, mode_t ipc_perm,
+ key_t ipc_key, mode_t ipc_perm, int ipc_gid,
struct slave_params *params,
snd_config_t *bindings,
int slowptr,
dsnoop->ipc_key = ipc_key;
dsnoop->ipc_perm = ipc_perm;
+ dsnoop->ipc_gid = ipc_gid;
dsnoop->semid = -1;
dsnoop->shmid = -1;
int bsize, psize, ipc_key_add_uid = 0, slowptr = 0;
key_t ipc_key = 0;
mode_t ipc_perm = 0600;
+ int ipc_gid = -1;
int err;
snd_config_for_each(i, next, conf) {
ipc_perm = strtol(perm, &endp, 8);
continue;
}
+ if (strcmp(id, "ipc_gid") == 0) {
+ char *group;
+ char *endp;
+ err = snd_config_get_ascii(n, &group);
+ if (err < 0) {
+ SNDERR("The field ipc_gid must be a valid group");
+ return err;
+ }
+ if (isdigit(*group) == 0) {
+ struct group *grp = getgrnam(group);
+ if (group == NULL) {
+ SNDERR("The field ipc_gid must be a valid group (create group %s)", grp);
+ return -EINVAL;
+ }
+ ipc_gid = grp->gr_gid;
+ } else {
+ ipc_perm = strtol(group, &endp, 10);
+ }
+ continue;
+ }
if (strcmp(id, "ipc_key_add_uid") == 0) {
err = snd_config_get_bool(n);
if (err < 0) {
params.period_size = psize;
params.buffer_size = bsize;
- err = snd_pcm_dsnoop_open(pcmp, name, ipc_key, ipc_perm, ¶ms, bindings, slowptr, root, sconf, stream, mode);
+ err = snd_pcm_dsnoop_open(pcmp, name, ipc_key, ipc_perm, ipc_gid, ¶ms, bindings, slowptr, root, sconf, stream, mode);
if (err < 0)
snd_config_delete(sconf);
return err;