[[!meta copyright="Copyright © 2012 Free Software Foundation, Inc."]]

[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable
id="license" text="Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no Invariant
Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the license
is included in the section entitled [[GNU Free Documentation
License|/fdl]]."]]"""]]


memstat
=======

Lists all the processes, executables, and shared libraries that are using up virtual memory. It's helpful to see how the shared memory is used and which 'old' libs are loaded.  
**Home page**: [[http://sourceforge.net/projects/memstattool]]

[[!toc startlevel=2]]


* * *


Log
---

* **Started**: 2012-01-20
* **Discussed**: [2012-01-21](http://lists.debian.org/debian-hurd/2012/01/msg00081.html)
* **Draft Submitted**: [2012-01-25](http://lists.debian.org/debian-hurd/2012/01/msg00122.html)
* **Submitted**: 2012-02-02, Bug#[658384](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=658384)
* **Stopped**: 2012-02-07, depends on `/proc` which is not yet totally implemented on the Hurd.
* **Accepted**: -


* * *


ToDo
----

Here is the output of `grep -R PATH_MAX memstat-0.9/*`:

    memstat.c:    char *p, major[8], minor[8], buff[PATH_MAX + 300], *path, perm[4];
    memstat.c:    char linkname[PATH_MAX], filename[PATH_MAX];
    memstat.c:    if ((len = readlink(filename, linkname, PATH_MAX)) == -1) {


* * *


Comments
--------

Here are comments on the patch...

    +#define FMT_PROC_MAPS "/proc/%d/maps"
    +#define FMT_PROC_EXE  "/proc/%d/exe"

Define string formats.

     static void read_proc(void)
     {
         unsigned int nread, pid;
         unsigned long inode, lo, hi, offs;
    -    char *p, major[8], minor[8], buff[PATH_MAX + 300], *path, perm[4];
    +    char *p, major[8], minor[8], *path, perm[4];
    +    char *buff = NULL;
    +    size_t buff_size = 0;

In this function we turn `buff` into dynamically allocated string.


    -   sprintf(buff, "/proc/%d/maps", pid);
    -   f = fopen(buff, "r");
    +   char filename[sizeof(FMT_PROC_MAPS) + (sizeof(int) * 3) + 1];
    +   sprintf(filename, FMT_PROC_MAPS, pid);
    +   f = fopen(filename, "r");

Compute the maximum size of `filename` using `sizeof(int) * 3` as explainend in the [[porting guide|porting_guide_for_dummies]].


    -   while (fgets(buff, sizeof(buff), f)) {
    +   while (!feof(f)) {
    +       buff = get_line(f);
    +       if (buff == NULL)
    +       break;

Read a line from the file using [[get_line()|porting_guide_for_dummies]].


    -       if ((strlen(buff) == 10) && (strcmp(buff, " (deleted)") == 0))
    +       if ((strlen(buff) == 10) && (strcmp(buff, " (deleted)") == 0)) {
    +       free(buff);
            continue;
    +       }
            nread = sscanf(buff, "%lx %lx %4s %lx %s %s %lu %as", &lo, &hi, perm, &offs, major, minor, &inode, &path);
    +       free(buff);

Free the `buff` when it's not used anymore.


    +       buff_size = 4; /* size of the format string without "%x" expressions */
    +       buff_size += strlen(major);
    +       buff_size += strlen(minor);
    +       buff_size += sizeof(int) * 3 + 1; /* inode */
    +       buff_size += 1; /* '\0' */
    +       buff = malloc(buff_size);
    +       if (buff == NULL) {
    +           perror("Cannot allocate memory!");
    +           exit(1);
    +       }

Compute the size that the `buff` must have.


    -   char linkname[PATH_MAX], filename[PATH_MAX];
    -   ssize_t len;
    +   char *linkname = NULL;
    +   struct stat sb;
    +   ssize_t len = -1;

In this function we turn linkname into dynamically allocated string. 
filename will be declared later.


    -   sprintf(filename, "/proc/%d/exe", pid);
    -   if ((len = readlink(filename, linkname, PATH_MAX)) == -1) {
    +   char filename[sizeof(FMT_PROC_EXE) + (sizeof(int) * 3) + 1];
    +   sprintf(filename, FMT_PROC_EXE, pid);

Same as above with `FMT_PROC_MAPS`.


    +        char filename[sizeof(FMT_PROC_EXE) + (sizeof(int) * 3) + 1];
    +        sprintf(filename, FMT_PROC_EXE, pid);
    +        linkname = readlink_malloc(filename);
    +        if (linkname == NULL) {

Use `readlink_malloc()` as explained in the porting guide because `/proc/PID/exe` doesn't work with `readlink()` 


    +   free(linkname);

Free dynamically allocated variable that is not used anymore.