]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
ipcs: read shared memory values from /proc
authorSami Kerola <kerolasa@iki.fi>
Sun, 14 Oct 2012 15:01:05 +0000 (16:01 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 23 Nov 2012 13:58:21 +0000 (14:58 +0100)
[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>
sys-utils/ipcs.c
sys-utils/ipcutils.c
sys-utils/ipcutils.h

index b904bb326bc2633571f986654689791e98cc17c1..496fc334c1d19e925042ec860dd308c6bbd7cc37 100644 (file)
 
 #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;
 }
 
index 041f350622b0d79540ca05b7b3ad0be1133b086b..c266ad8680ced489a576d816c42b43ec9a2f0af3 100644 (file)
@@ -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);
+}
index ef539ee6c3f8c9dd6c60947c970bea44a3912a38..8e2bfddfb8fdeb055917b465c5a8b08a63b7c210 100644 (file)
@@ -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 */