From 058e81540fbb0d2b780245361fa13376478b7375 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Sun, 14 Oct 2012 16:01:05 +0100 Subject: 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 Signed-off-by: Karel Zak --- sys-utils/ipcs.c | 73 +++++++++++++-------------- sys-utils/ipcutils.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ sys-utils/ipcutils.h | 33 ++++++++++++ 3 files changed, 205 insertions(+), 39 deletions(-) (limited to 'sys-utils') 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 + #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 */ -- cgit v1.2.3-55-g7522