diff options
author | Sami Kerola | 2012-11-11 21:53:07 +0100 |
---|---|---|
committer | Karel Zak | 2012-11-23 14:58:22 +0100 |
commit | 1e2418a234e2361fe1916a835ea59aa19c0e4810 (patch) | |
tree | 6a01bcce8200edc95cb2b246cd9967e03f55a522 | |
parent | ipcs: make individual shared memory id printing to use /proc (diff) | |
download | kernel-qcow2-util-linux-1e2418a234e2361fe1916a835ea59aa19c0e4810.tar.gz kernel-qcow2-util-linux-1e2418a234e2361fe1916a835ea59aa19c0e4810.tar.xz kernel-qcow2-util-linux-1e2418a234e2361fe1916a835ea59aa19c0e4810.zip |
ipcs: clean up do_sem(), and add ipc_sem_get_info()
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
-rw-r--r-- | sys-utils/ipcs.c | 80 | ||||
-rw-r--r-- | sys-utils/ipcutils.c | 109 | ||||
-rw-r--r-- | sys-utils/ipcutils.h | 15 |
3 files changed, 164 insertions, 40 deletions
diff --git a/sys-utils/ipcs.c b/sys-utils/ipcs.c index 4945d8dcc..1180299eb 100644 --- a/sys-utils/ipcs.c +++ b/sys-utils/ipcs.c @@ -33,8 +33,8 @@ static void do_shm (char format); static void print_shm (int id); +static void do_sem (char format); -void do_sem (char format); void do_msg (char format); void print_msg (int id); void print_sem (int id); @@ -332,25 +332,16 @@ static void do_shm (char format) return; } -void do_sem (char format) +static void do_sem (char format) { - int maxid, semid, id; - struct semid_ds semary; - struct seminfo seminfo; - struct ipc_perm *ipcp = &semary.sem_perm; struct passwd *pw; - union semun arg; - struct ipc_limits lim; - - arg.array = (ushort *) (void *) &seminfo; - maxid = semctl (0, 0, SEM_INFO, arg); - if (maxid < 0) { - printf (_("kernel not configured for semaphores\n")); - return; - } + struct sem_data *semds, *semdsp; switch (format) { case LIMITS: + { + struct ipc_limits lim; + printf (_("------ Semaphore Limits --------\n")); if (ipc_sem_get_limits(&lim)) return; @@ -360,12 +351,21 @@ void do_sem (char format) printf (_("max ops per semop call = %d\n"), lim.semopm); printf (_("semaphore max value = %d\n"), lim.semvmx); return; - + } case STATUS: + { + struct seminfo seminfo; + union semun arg; + arg.array = (ushort *) (void *) &seminfo; + if (semctl (0, 0, SEM_INFO, arg) < 0) { + printf (_("kernel not configured for semaphores\n")); + return; + } printf (_("------ Semaphore Status --------\n")); printf (_("used arrays = %d\n"), seminfo.semusz); printf (_("allocated semaphores = %d\n"), seminfo.semaem); return; + } case CREATOR: printf (_("------ Semaphore Arrays Creators/Owners --------\n")); @@ -389,48 +389,48 @@ void do_sem (char format) break; } - for (id = 0; id <= maxid; id++) { - arg.buf = (struct semid_ds *) &semary; - semid = semctl (id, 0, SEM_STAT, arg); - if (semid < 0) - continue; + /* + * Print data + */ + if (ipc_sem_get_info(-1, &semds) < 1) + return; + semdsp = semds; + + for (semdsp = semds; semdsp->next != NULL; semdsp = semdsp->next) { if (format == CREATOR) { - print_perms (semid, ipcp); + ipc_print_perms(stdout, &semdsp->sem_perm); continue; } - pw = getpwuid(ipcp->uid); + pw = getpwuid(semdsp->sem_perm.uid); switch (format) { case TIME: if (pw) - printf ("%-8d %-10.10s", semid, pw->pw_name); + printf ("%-8d %-10.10s", semdsp->sem_perm.id, pw->pw_name); else - printf ("%-8d %-10u", semid, ipcp->uid); - printf (" %-26.24s", semary.sem_otime - ? ctime(&semary.sem_otime) : _("Not set")); - printf (" %-26.24s\n", semary.sem_ctime - ? ctime(&semary.sem_ctime) : _("Not set")); + printf ("%-8d %-10u", semdsp->sem_perm.id, semdsp->sem_perm.uid); + printf (" %-26.24s", semdsp->sem_otime + ? ctime(&semdsp->sem_otime) : _("Not set")); + printf (" %-26.24s\n", semdsp->sem_ctime + ? ctime(&semdsp->sem_ctime) : _("Not set")); break; case PID: break; default: - printf("0x%08x ", ipcp->KEY); + printf("0x%08x ", semdsp->sem_perm.key); if (pw) - printf ("%-10d %-10.10s", semid, pw->pw_name); + printf ("%-10d %-10.10s", semdsp->sem_perm.id, pw->pw_name); else - printf ("%-10d %-10u", semid, ipcp->uid); + printf ("%-10d %-10u", semdsp->sem_perm.id, semdsp->sem_perm.uid); printf (" %-10o %-10ld\n", - ipcp->mode & 0777, - /* - * glibc-2.1.3 and earlier has unsigned - * short. glibc-2.1.91 has variation between - * unsigned short and unsigned long. Austin - * prescribes unsigned short. - */ - (long) semary.sem_nsems); + semdsp->sem_perm.mode & 0777, + semdsp->sem_nsems); break; } } + + ipc_sem_free_info(semds); + return; } void do_msg (char format) diff --git a/sys-utils/ipcutils.c b/sys-utils/ipcutils.c index 3b52a7e6b..61671c128 100644 --- a/sys-utils/ipcutils.c +++ b/sys-utils/ipcutils.c @@ -211,6 +211,115 @@ void ipc_shm_free_info(struct shm_data *shmds) } } +int ipc_sem_get_info(int id, struct sem_data **semds) +{ + FILE *f; + int i, maxid; + struct sem_data *p; + struct seminfo dummy; + union semun arg; + + p = *semds = xcalloc(1, sizeof(struct sem_data)); + p->next = NULL; + + f = path_fopen("r", 0, _PATH_PROC_SYSV_SEM); + if (!f) + goto sem_fallback; + + while (fgetc(f) != '\n') ; /* skip header */ + + while (feof(f) == 0) { + if (fscanf(f, + "%d %d %o %" SCNu64 " %u %u %u %u %" SCNu64 " %" SCNu64 "\n", + &p->sem_perm.key, + &p->sem_perm.id, + &p->sem_perm.mode, + &p->sem_nsems, + &p->sem_perm.uid, + &p->sem_perm.gid, + &p->sem_perm.cuid, + &p->sem_perm.cgid, + &p->sem_otime, + &p->sem_ctime) != 10) + continue; + + if (id > -1) { + /* ID specified */ + if (id == p->sem_perm.id) { + i = 1; + break; + } else + continue; + } + + p->next = xcalloc(1, sizeof(struct sem_data)); + p = p->next; + p->next = NULL; + i++; + } + + if (i == 0) + free(*semds); + fclose(f); + return i; + + /* Fallback; /proc or /sys file(s) missing. */ + sem_fallback: + i = id < 0 ? 0 : id; + + arg.array = (ushort *) (void *)&dummy; + maxid = semctl(0, 0, SEM_INFO, arg); + if (maxid < 0) + return 0; + + while (i <= maxid) { + int semid; + struct semid_ds semseg; + struct ipc_perm *ipcp = &semseg.sem_perm; + arg.buf = (struct semid_ds *)&semseg; + + semid = semctl(i, 0, SEM_STAT, arg); + if (semid < 0) { + if (-1 < id) { + free(*semds); + return 0; + } + i++; + continue; + } + + p->sem_perm.key = ipcp->KEY; + p->sem_perm.id = semid; + p->sem_perm.mode = ipcp->mode; + p->sem_nsems = semseg.sem_nsems; + p->sem_perm.uid = ipcp->uid; + p->sem_perm.gid = ipcp->gid; + p->sem_perm.cuid = ipcp->cuid; + p->sem_perm.cgid = ipcp->cuid; + p->sem_otime = semseg.sem_otime; + p->sem_ctime = semseg.sem_ctime; + + if (id < 0) { + p->next = xcalloc(1, sizeof(struct sem_data)); + p = p->next; + p->next = NULL; + i++; + } else + return 1; + } + + return i; +} + +void ipc_sem_free_info(struct sem_data *semds) +{ + while (semds) { + struct sem_data *next = semds->next; + free(semds); + semds = next; + } +} + void ipc_print_perms(FILE *f, struct ipc_stat *is) { struct passwd *pw; diff --git a/sys-utils/ipcutils.h b/sys-utils/ipcutils.h index 45a75d84f..3ab5da0ca 100644 --- a/sys-utils/ipcutils.h +++ b/sys-utils/ipcutils.h @@ -132,4 +132,19 @@ struct shm_data { extern int ipc_shm_get_info(int id, struct shm_data **shmds); extern void ipc_shm_free_info(struct shm_data *shmds); +/* See 'struct sem_array' in kernel sources + */ +struct sem_data { + struct ipc_stat sem_perm; + + time_t sem_ctime; + time_t sem_otime; + uint64_t sem_nsems; + + struct sem_data *next; +}; + +extern int ipc_sem_get_info(int id, struct sem_data **semds); +extern void ipc_sem_free_info(struct sem_data *semds); + #endif /* UTIL_LINUX_IPCUTILS_H */ |