summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Kerola2012-10-14 17:01:05 +0200
committerKarel Zak2012-11-23 14:58:21 +0100
commit058e81540fbb0d2b780245361fa13376478b7375 (patch)
tree00aa984458223ade6f0f5d11609b3bef4743185a
parentipcs: determine ipc limits from /proc (diff)
downloadkernel-qcow2-util-linux-058e81540fbb0d2b780245361fa13376478b7375.tar.gz
kernel-qcow2-util-linux-058e81540fbb0d2b780245361fa13376478b7375.tar.xz
kernel-qcow2-util-linux-058e81540fbb0d2b780245361fa13376478b7375.zip
ipcs: read shared memory values from /proc
[kzak@redhat.com: - move to ipcutils.{c,h}, - fix datatypes to be arch independent] Signed-off-by: Sami Kerola <kerolasa@iki.fi> Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--sys-utils/ipcs.c73
-rw-r--r--sys-utils/ipcutils.c138
-rw-r--r--sys-utils/ipcutils.h33
3 files changed, 205 insertions, 39 deletions
diff --git a/sys-utils/ipcs.c b/sys-utils/ipcs.c
index b904bb326..496fc334c 100644
--- a/sys-utils/ipcs.c
+++ b/sys-utils/ipcs.c
@@ -25,14 +25,14 @@
#include "ipcutils.h"
-
#define LIMITS 1
#define STATUS 2
#define CREATOR 3
#define TIME 4
#define PID 5
-void do_shm (char format);
+static void do_shm (char format);
+
void do_sem (char format);
void do_msg (char format);
void print_shm (int id);
@@ -190,14 +190,13 @@ static void print_perms (int id, struct ipc_perm *ipcp)
printf(" %-10u\n", ipcp->gid);
}
-void do_shm (char format)
+static void do_shm (char format)
{
- int maxid, shmid, id;
- struct shmid_ds shmseg;
+ int maxid;
struct shm_info shm_info;
- struct ipc_perm *ipcp = &shmseg.shm_perm;
struct passwd *pw;
struct ipc_limits lim;
+ struct shm_data *shmds, *shmdsp;
maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
if (maxid < 0) {
@@ -269,60 +268,56 @@ void do_shm (char format)
break;
}
- for (id = 0; id <= maxid; id++) {
- shmid = shmctl (id, SHM_STAT, &shmseg);
- if (shmid < 0)
- continue;
+ if (ipc_shm_get_info(maxid, -1, &shmds) < 1)
+ return;
+ shmdsp = shmds;
+
+ for (shmdsp = shmds; shmdsp->next != NULL; shmdsp = shmdsp->next) {
if (format == CREATOR) {
- print_perms (shmid, ipcp);
+ ipc_print_perms(stdout, &shmdsp->shm_perm);
continue;
}
- pw = getpwuid(ipcp->uid);
+ pw = getpwuid(shmdsp->shm_perm.uid);
switch (format) {
case TIME:
if (pw)
- printf ("%-10d %-10.10s", shmid, pw->pw_name);
+ printf ("%-10d %-10.10s", shmdsp->shm_perm.id, pw->pw_name);
else
- printf ("%-10d %-10u", shmid, ipcp->uid);
+ printf ("%-10d %-10u", shmdsp->shm_perm.id, shmdsp->shm_perm.uid);
/* ctime uses static buffer: use separate calls */
- printf(" %-20.16s", shmseg.shm_atime
- ? ctime(&shmseg.shm_atime) + 4 : _("Not set"));
- printf(" %-20.16s", shmseg.shm_dtime
- ? ctime(&shmseg.shm_dtime) + 4 : _("Not set"));
- printf(" %-20.16s\n", shmseg.shm_ctime
- ? ctime(&shmseg.shm_ctime) + 4 : _("Not set"));
+ printf(" %-20.16s", shmdsp->shm_atim
+ ? ctime(&shmdsp->shm_atim) + 4 : _("Not set"));
+ printf(" %-20.16s", shmdsp->shm_dtim
+ ? ctime(&shmdsp->shm_dtim) + 4 : _("Not set"));
+ printf(" %-20.16s\n", shmdsp->shm_ctim
+ ? ctime(&shmdsp->shm_ctim) + 4 : _("Not set"));
break;
case PID:
if (pw)
- printf ("%-10d %-10.10s", shmid, pw->pw_name);
+ printf ("%-10d %-10.10s", shmdsp->shm_perm.id, pw->pw_name);
else
- printf ("%-10d %-10u", shmid, ipcp->uid);
- printf (" %-10d %-10d\n",
- shmseg.shm_cpid, shmseg.shm_lpid);
+ printf ("%-10d %-10u", shmdsp->shm_perm.id, shmdsp->shm_perm.uid);
+ printf (" %-10u %-10u\n",
+ shmdsp->shm_cprid, shmdsp->shm_lprid);
break;
default:
- printf("0x%08x ",ipcp->KEY );
+ printf("0x%08x ", shmdsp->shm_perm.key);
if (pw)
- printf ("%-10d %-10.10s", shmid, pw->pw_name);
+ printf ("%-10d %-10.10s", shmdsp->shm_perm.id, pw->pw_name);
else
- printf ("%-10d %-10u", shmid, ipcp->uid);
+ printf ("%-10d %-10u", shmdsp->shm_perm.id, shmdsp->shm_perm.uid);
printf (" %-10o %-10lu %-10ld %-6s %-6s\n",
- ipcp->mode & 0777,
- /*
- * earlier: int, Austin has size_t
- */
- (unsigned long) shmseg.shm_segsz,
- /*
- * glibc-2.1.3 and earlier has unsigned short;
- * Austin has shmatt_t
- */
- (long) shmseg.shm_nattch,
- ipcp->mode & SHM_DEST ? _("dest") : " ",
- ipcp->mode & SHM_LOCKED ? _("locked") : " ");
+ shmdsp->shm_perm.mode & 0777,
+ shmdsp->shm_segsz,
+ shmdsp->shm_nattch,
+ shmdsp->shm_perm.mode & SHM_DEST ? _("dest") : " ",
+ shmdsp->shm_perm.mode & SHM_LOCKED ? _("locked") : " ");
break;
}
}
+
+ ipc_shm_free_info(shmds);
return;
}
diff --git a/sys-utils/ipcutils.c b/sys-utils/ipcutils.c
index 041f35062..c266ad868 100644
--- a/sys-utils/ipcutils.c
+++ b/sys-utils/ipcutils.c
@@ -1,5 +1,8 @@
+#include <inttypes.h>
+
#include "c.h"
+#include "xalloc.h"
#include "path.h"
#include "pathnames.h"
#include "ipcutils.h"
@@ -87,3 +90,138 @@ int ipc_shm_get_limits(struct ipc_limits *lim)
return 0;
}
+
+int ipc_shm_get_info(int maxid, int id, struct shm_data **shmds)
+{
+ FILE *f;
+ int i;
+ struct shm_data *p;
+
+ p = *shmds = xmalloc(sizeof(struct shm_data));
+ p->next = NULL;
+
+ f = path_fopen("r", 0, _PATH_PROC_SYSV_SHM);
+ if (!f)
+ goto fallback;
+
+ while (fgetc(f) != '\n'); /* skip header */
+
+ for (i = 0; !feof(f); i++) {
+ if (fscanf(f,
+ "%d %d %o %"SCNu64 " %u %u "
+ "%"SCNu64 " %u %u %u %u %"SCNu64 " %"SCNu64 " %"SCNu64
+ " %"SCNu64 " %"SCNu64 "\n",
+ &p->shm_perm.key,
+ &p->shm_perm.id,
+ &p->shm_perm.mode,
+ &p->shm_segsz,
+ &p->shm_cprid,
+ &p->shm_lprid,
+ &p->shm_nattch,
+ &p->shm_perm.uid,
+ &p->shm_perm.gid,
+ &p->shm_perm.cuid,
+ &p->shm_perm.cgid,
+ &p->shm_atim,
+ &p->shm_dtim,
+ &p->shm_ctim,
+ &p->shm_rss,
+ &p->shm_swp) != 16)
+ continue;
+
+ if (id < 0) {
+ p->next = xmalloc(sizeof(struct shm_data));
+ p = p->next;
+ p->next = NULL;
+ }
+ }
+
+ if (i == 0)
+ free(*shmds);
+ fclose(f);
+ return i;
+
+ /* Fallback; /proc or /sys file(s) missing. */
+fallback:
+ i = id < 0 ? 0 : id;
+
+ while (i <= maxid) {
+ int shmid;
+ struct shmid_ds shmseg;
+ struct ipc_perm *ipcp = &shmseg.shm_perm;
+
+ shmid = shmctl(i, SHM_STAT, &shmseg);
+ if (shmid < 0) {
+ if (-1 < id) {
+ free(*shmds);
+ return 0;
+ }
+ i++;
+ continue;
+ }
+
+ p->shm_perm.key = ipcp->KEY;
+ p->shm_perm.id = shmid;
+ p->shm_perm.mode = ipcp->mode;
+ p->shm_segsz = shmseg.shm_segsz;
+ p->shm_cprid = shmseg.shm_cpid;
+ p->shm_lprid = shmseg.shm_lpid;
+ p->shm_nattch = shmseg.shm_nattch;
+ p->shm_perm.uid = ipcp->uid;
+ p->shm_perm.gid = ipcp->gid;
+ p->shm_perm.cuid = ipcp->cuid;
+ p->shm_perm.cgid = ipcp->cuid;
+ p->shm_atim = shmseg.shm_atime;
+ p->shm_dtim = shmseg.shm_dtime;
+ p->shm_ctim = shmseg.shm_ctime;
+ p->shm_rss = 0xdead;
+ p->shm_swp = 0xdead;
+
+ if (id < 0) {
+ p->next = xmalloc(sizeof(struct shm_data));
+ p = p->next;
+ p->next = NULL;
+ i++;
+ } else
+ return 1;
+ }
+
+ return i;
+}
+
+void ipc_shm_free_info(struct shm_data *shmds)
+{
+ while (shmds) {
+ struct shm_data *next = shmds->next;
+ free(shmds);
+ shmds = next;
+ }
+}
+
+void ipc_print_perms(FILE *f, struct ipc_stat *is)
+{
+ struct passwd *pw;
+ struct group *gr;
+
+ fprintf(f, "%-10d %-10o", is->id, is->mode & 0777);
+
+ if ((pw = getpwuid(is->cuid)))
+ fprintf(f, " %-10s", pw->pw_name);
+ else
+ fprintf(f, " %-10u", is->cuid);
+
+ if ((gr = getgrgid(is->cgid)))
+ fprintf(f, " %-10s", gr->gr_name);
+ else
+ fprintf(f, " %-10u", is->cgid);
+
+ if ((pw = getpwuid(is->uid)))
+ fprintf(f, " %-10s", pw->pw_name);
+ else
+ fprintf(f, " %-10u", is->uid);
+
+ if ((gr = getgrgid(is->gid)))
+ fprintf(f, " %-10s\n", gr->gr_name);
+ else
+ fprintf(f, " %-10u\n", is->gid);
+}
diff --git a/sys-utils/ipcutils.h b/sys-utils/ipcutils.h
index ef539ee6c..8e2bfddfb 100644
--- a/sys-utils/ipcutils.h
+++ b/sys-utils/ipcutils.h
@@ -99,4 +99,37 @@ extern int ipc_msg_get_limits(struct ipc_limits *lim);
extern int ipc_sem_get_limits(struct ipc_limits *lim);
extern int ipc_shm_get_limits(struct ipc_limits *lim);
+struct ipc_stat {
+ int id;
+ key_t key;
+ uid_t uid; /* current uid */
+ gid_t gid; /* current gid */
+ uid_t cuid; /* creator uid */
+ gid_t cgid; /* creator gid */
+ unsigned int mode;
+};
+
+extern void ipc_print_perms(FILE *f, struct ipc_stat *is);
+
+/* See 'struct shmid_kernel' in kernel sources
+ */
+struct shm_data {
+ struct ipc_stat shm_perm;
+
+ uint64_t shm_nattch;
+ uint64_t shm_segsz;
+ time_t shm_atim;
+ time_t shm_dtim;
+ time_t shm_ctim;
+ pid_t shm_cprid;
+ pid_t shm_lprid;
+ uint64_t shm_rss;
+ uint64_t shm_swp;
+
+ struct shm_data *next;
+};
+
+extern int ipc_shm_get_info(int maxid, int id, struct shm_data **shmds);
+extern void ipc_shm_free_info(struct shm_data *shmds);
+
#endif /* UTIL_LINUX_IPCUTILS_H */