summaryrefslogblamecommitdiff
path: root/src/bin/evas/evas_cserve2_shm_debug.c
blob: 341d8edd9fd341de22afeb203bf12791c97f6ea0 (plain) (tree)

























































































































































                                                                                





















                                                                             
                                                       










                                                              
                                                         





























































































                                                                            







                                                      

























































































                                                                                
                        















                                                                              
                                               

                                                                  
                                                                   








                                                                          


































                                                                                      
                                                                  








                          




















































                                                                               

                                      

                                               

                                         

                                                                 












































                                                                                     

                                                                                          

                                                                               
                                                                                 






























































                                                                             
                                                                       









                                           
                                                                         
                                                                              
                                                                                 
                                                               



















                                                                             

                                                             



























































                                                                                 

                                                      
































































                                                                     

                                    














                                      
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <unistd.h>
#include <sys/ioctl.h>

#include <Eina.h>
#include "evas_cs2.h"

#define SHM_FOLDER "/dev/shm"
static int _evas_cserve2_shm_debug_log_dom = -1;

#define ERR(...) EINA_LOG_DOM_ERR(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
#define DBG(...) EINA_LOG_DOM_DBG(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)

typedef struct _Shm_File Shm_File;
struct _Shm_File
{
   Eina_File *f;
   char *data;
   size_t size;
   int tag;

   Eina_Bool strings;
   Shared_Array_Header *header;
};

Shm_File *sf_strindex = NULL;
Shm_File *sf_strpool = NULL;
Shm_File *sf_fonts = NULL;
Shm_File *sf_files = NULL;
Shm_File *sf_images = NULL;

static int _termsize = 0;

static void
nprintf(int n, const char *fmt, ...)
{
   char buf[n+1];
   va_list arg;
   int len;

   va_start(arg, fmt);
   if (!n)
     vprintf(fmt, arg);
   else
     {
        len = vsnprintf(buf, n+1, fmt, arg);
        buf[n] = 0;
        fputs(buf, stdout);
        if ((len > 0) && (buf[len-1] != '\n'))
          fputc('\n', stdout);
     }
   va_end(arg);
}

#define printf(...) nprintf(_termsize, __VA_ARGS__)

static Shm_File *
_shm_file_open(const char *path)
{
   Shm_File *sf;
   Eina_File *f;
   char *data;

   f = eina_file_open(path, EINA_TRUE);
   if (!f)
     {
        ERR("Could not open file %s: [%d] %m", path, errno);
        return NULL;
     }

   data = eina_file_map_all(f, EINA_FILE_RANDOM);
   if (!data)
     {
        ERR("Could not map the file %s", path);
        eina_file_close(f);
        return NULL;
     }

   sf = calloc(1, sizeof(*sf));
   sf->data = data;
   sf->f = f;
   sf->size = eina_file_size_get(f);

   DBG("Successfully opened %s", path);
   return sf;
}

static void
_shm_file_close(Shm_File *sf)
{
   if (!sf) return;
   eina_file_map_free(sf->f, sf->data);
   eina_file_close(sf->f);
   free(sf);
}

static Eina_Bool
_shm_file_probe(Shm_File *sf)
{
   if (!sf || !sf->data)
     return EINA_FALSE;

   if (sf->size < sizeof(Shared_Array_Header))
     {
        sf->header = NULL;
        return EINA_TRUE;
     }

   sf->header = (Shared_Array_Header *) sf->data;
   switch (sf->header->tag)
     {
      case STRING_INDEX_ARRAY_TAG:
        DBG("Found string index: %s", eina_file_filename_get(sf->f));
        if (sf->header->elemsize != sizeof(Index_Entry))
          {
             ERR("String index looks invalid: elemsize %d",
                 sf->header->elemsize);
             return EINA_FALSE;
          }
        sf->tag = STRING_INDEX_ARRAY_TAG;
        sf_strindex = sf;
        break;

      case STRING_MEMPOOL_FAKETAG:
        DBG("Found string mempool: %s", eina_file_filename_get(sf->f));
        sf->strings = EINA_TRUE;
        sf->tag = STRING_MEMPOOL_FAKETAG;
        sf->header = NULL;
        sf_strpool = sf;
        break;

      case FILE_DATA_ARRAY_TAG:
        DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
        sf->tag = sf->header->tag;
        sf_files = sf;
        break;

      case IMAGE_DATA_ARRAY_TAG:
        DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
        sf->tag = sf->header->tag;
        sf_images = sf;
        break;

      case FONT_DATA_ARRAY_TAG:
        DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
        sf->tag = sf->header->tag;
        sf_fonts = sf;
        break;

      case GLYPH_DATA_ARRAY_TAG:
        DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
        sf->tag = sf->header->tag;
        break;

      default:
        //DBG("Unknown tag found: %d", sf->header->tag);
        sf->header = NULL;
        break;
     }

   return EINA_TRUE;
}

static Eina_List *
_shm_files_list(const char *folder)
{
   Eina_List *lst = NULL;
   Eina_Iterator *iter;
   const Eina_File_Direct_Info *f_info;
   char pattern[64];

   sprintf(pattern, "/evas-shm-%05d-", (int) getuid());
   iter = eina_file_direct_ls(folder);
   EINA_ITERATOR_FOREACH(iter, f_info)
     {
        if (strstr(f_info->path, pattern))
          {
             const char *shmname = strrchr(f_info->path, '/');
             if (!shmname) continue;

             lst = eina_list_append(lst, strdup(shmname));
          }
        else
          DBG("cserve2 scan: ignoring %s", f_info->path);
     }
   eina_iterator_free(iter);

   return lst;
}

static void
printf_newline(Eina_Bool flush)
{
   printf("----------------------------------------------------------------"
          "----------------\n");

   if (flush)
     {
        printf("\n\n");
        fflush(stdout);
     }
}

static void
_index_tables_summary_print(void)
{
   printf("Shared index tables\n\n");
   printf("Table     Tag MapSize  Gen ElSz Count  Last  Sort Path\n");
   printf_newline(0);

   printf("StrIdx   %4.4s %7d %4d %4d %5d %5d %5d %s\n",
          (char *) &sf_strindex->tag,
          (int) eina_file_size_get(sf_strindex->f),
          sf_strindex->header->generation_id, sf_strindex->header->elemsize,
          sf_strindex->header->count, sf_strindex->header->emptyidx,
          sf_strindex->header->sortedidx,
          eina_file_filename_get(sf_strindex->f));

   printf("StrData  %4.4s %7d                             %s\n",
          (char *) &sf_strpool->tag,
          (int) eina_file_size_get(sf_strpool->f),
          eina_file_filename_get(sf_strpool->f));

   if (sf_files)
     printf("FileIdx  %4.4s %7d %4d %4d %5d %5d %5d %s\n",
            (char *) &sf_files->tag,
            (int) eina_file_size_get(sf_files->f),
            sf_files->header->generation_id, sf_files->header->elemsize,
            sf_files->header->count, sf_files->header->emptyidx,
            sf_files->header->sortedidx,
            eina_file_filename_get(sf_files->f));
   else
     printf("FileIdx  <not found>\n");

   if (sf_images)
     printf("Images   %4.4s %7d %4d %4d %5d %5d %5d %s\n",
            (char *) &sf_images->tag,
            (int) eina_file_size_get(sf_images->f),
            sf_images->header->generation_id, sf_images->header->elemsize,
            sf_images->header->count, sf_images->header->emptyidx,
            sf_images->header->sortedidx,
            eina_file_filename_get(sf_images->f));
   else
     printf("Images   <not found>\n");

   if (sf_fonts)
     printf("FontIdx  %4.4s %7d %4d %4d %5d %5d %5d %s\n",
            (char *) &sf_fonts->tag,
            (int) eina_file_size_get(sf_fonts->f),
            sf_fonts->header->generation_id, sf_fonts->header->elemsize,
            sf_fonts->header->count, sf_fonts->header->emptyidx,
            sf_fonts->header->sortedidx,
            eina_file_filename_get(sf_fonts->f));
   else
     printf("FontIdx  <not found>\n");

   printf_newline(1);
}

static const Shm_Object *
_shared_index_item_get_by_id(Shm_File *si, int elemsize, unsigned int id)
{
   const Shm_Object *obj;
   const char *base;
   int low = 0, high, start_high;
   int cur;

   if (!si || elemsize <= 0 || !id)
     return NULL;

   // FIXME: HACK (consider all arrays always sorted by id)
   high = si->header->emptyidx; // Should be si->header->sortedidx

   if (high > si->header->count)
     high = si->header->count;

   base = si->data  + sizeof(Shared_Array_Header);

   // Direct access, works for non-repacked arrays
   if ((int) id < high)
     {
        obj = (Shm_Object *) (base + (elemsize * id));
        if (obj->id == id)
          return obj;
     }

   // Binary search
   start_high = high;
   while(high != low)
     {
        cur = low + ((high - low) / 2);
        obj = (Shm_Object *) (base + (elemsize * cur));
        if (obj->id == id)
          return obj;
        if (obj->id < id)
          low = cur + 1;
        else
          high = cur;
     }

   // Linear search
   for (cur = start_high; cur < si->header->count; cur++)
     {
        obj = (Shm_Object *) (base + (elemsize * cur));
        if (!obj->id)
          return NULL;
        if (obj->id == id)
          return obj;
     }

   return NULL;
}

static void *
_shared_array_item_get(Shm_File *sf, int idx)
{
   if (!sf || !sf->header || idx < 0)
     return NULL;

   if ((idx + 1) * sf->header->elemsize > (int) sf->size)
     return NULL;

   return (sf->data + sizeof(Shared_Array_Header) + idx * sf->header->elemsize);
}

static const char *
_shared_string_get(int id)
{
   Index_Entry *ie;

   ie = (Index_Entry *)
         _shared_index_item_get_by_id(sf_strindex, sizeof(*ie), id);
   if (!ie) return NULL;
   if (ie->offset < 0) return NULL;
   if (!ie->refcount) return NULL;
   if (ie->offset + ie->length > (int) sf_strpool->size) return NULL;

   return sf_strpool->data + ie->offset;
}

static void
_strings_all_print(Eina_Bool full)
{
   int k;
   const char *mindata = sf_strpool->data;
   const char *maxdata = sf_strpool->data + sf_strpool->size;

   printf("List of strings\n");
   printf("Indexes: %s\n", eina_file_filename_get(sf_strindex->f));
   printf("Data:    %s\n", eina_file_filename_get(sf_strpool->f));
   printf(" String   BufID  Refcnt  Offset  Buflen Content\n");
   printf_newline(0);

   for (k = 0; k < sf_strindex->header->count; k++)
     {
        Index_Entry *ie;
        const char *data;

        ie = _shared_array_item_get(sf_strindex, k);
        if (!ie) break;

        if (!ie->id || (!full && !ie->refcount))
          continue;

        data = sf_strpool->data + ie->offset;
        if ((data < mindata) || (data + ie->length > maxdata))
          data = "<invalid offset>";

        printf("%7d %7d %7d %7d %7d '%s'\n",
               k, ie->id, ie->refcount, ie->offset, ie->length, data);
     }

   printf_newline(1);
}

static void
_files_all_print_short()
{
   int k;

   if (!sf_files) return;

   printf("List of image files: %s\n", eina_file_filename_get(sf_files->f));
   printf("A: Alpha, I: Invalid.\n\n");
   printf("  Index  FileID WIDTHxHEIGHT A I Loader PathID  KeyID Path:Key\n");
   printf_newline(0);

   for (k = 0; k < sf_files->header->count; k++)
     {
        File_Data *fd;

        fd = _shared_array_item_get(sf_files, k);
        if (!fd) break;
        if (!fd->id || !fd->refcount) continue;

        printf("%7d %7d %5dx%-6d %d %d %6.6s %6d %6d '%s':'%s'\n",
               k, fd->id, fd->w, fd->h, !!fd->alpha, !!fd->changed,
               fd->loader_data ? _shared_string_get(fd->loader_data) : "",
               fd->path, fd->key, _shared_string_get(fd->path),
               _shared_string_get(fd->key));
     }

   printf_newline(1);
}

static void
_files_all_print_all(void)
{
   int k;

   if (!sf_files) return;

   printf("List of opened image files: %s\n", eina_file_filename_get(sf_files->f));
   printf_newline(0);

   for (k = 0; k < sf_files->header->count; k++)
     {
        File_Data *fd;

        fd = _shared_array_item_get(sf_files, k);
        if (!fd) break;
        if (!fd->id) continue;

        printf("File #%-8d %d\n", k, fd->id);
        printf("Path:Key:      '%s':'%s'\n",
               _shared_string_get(fd->path), _shared_string_get(fd->key));
        printf("LoadOpts:      Region:      %d,%d-%dx%d\n",
               fd->lo.region.x, fd->lo.region.y, fd->lo.region.w, fd->lo.region.h);
        if (fd->lo.dpi != 0)
          printf("               DPI:         %f\n");
        else
          printf("               DPI:         0\n");
        printf("               Requested:   %dx%d\n", fd->lo.w, fd->lo.h);
        printf("               Scale down:  %d\n", fd->lo.scale_down_by);
        printf("               Orientation: %s\n", fd->lo.orientation ? "YES" : "NO");
        printf("Loader:        %s\n", _shared_string_get(fd->loader_data));
        printf("Geometry:      %dx%d\n", fd->w, fd->h);
        printf("Animation:     anim: %s, frames: %d, loop: %d, hint: %d\n",
               fd->animated ? "YES" : "NO",
               fd->frame_count, fd->loop_count, fd->loop_hint);
        printf("Alpha:         %s\n", fd->alpha ? "YES" : "NO");
        printf("Changed:       %s\n", fd->changed ? "YES" : "NO");

        printf_newline(0);
     }

   printf("\n\n");
   fflush(stdout);
}

static void
_images_all_print_short(void)
{
   int k;

   if (!sf_images) return;

   printf("List of loaded images: %s\n", eina_file_filename_get(sf_images->f));
   printf("A: Sparse alpha, U: Unused, L: Load requested.\n\n");
   printf("  Index ImageID  FileID  Refcnt A U L   ShmID ShmPath\n");
   printf_newline(0);

   for (k = 0; k < sf_images->header->count; k++)
     {
        Image_Data *id;

        id = _shared_array_item_get(sf_images, k);
        if (!id) break;
        if (!id->id || !id->refcount) continue;

        printf("%7d %7d %7d %7d %d %d %d %7d '%s'\n",
               k, id->id, id->file_id, id->refcount,
               !!id->alpha_sparse, !!id->unused, !!id->doload, id->shm_id,
               id->shm_id ? _shared_string_get(id->shm_id) : "");
     }

   printf_newline(1);
}

static void
_images_all_print_full(void)
{
   int k;

   if (!sf_images) return;

   printf("List of loaded images: %s\n\n",
          eina_file_filename_get(sf_images->f));
   printf_newline(0);

   for (k = 0; k < sf_images->header->count; k++)
     {
        Image_Data *id;
        File_Data *fd;
        const char *scale_hint;

        id = _shared_array_item_get(sf_images, k);
        if (!id) break;
        if (!id->id) continue;

        printf("Image #%-8d %d\n", k, id->id);
        printf("Refcount        %d\n", id->refcount);
        printf("Sparse alpha    %s\n"
               "Unused:         %s\n"
               "Load requested: %s\n"
               "Valid:          %s\n",
               id->alpha_sparse ? "YES" : "NO",
               id->unused ? "YES" : "NO",
               id->doload ? "YES" : "NO",
               id->valid ? "YES" : "NO");
        printf("Shm Path:       '%s'\n",
               id->shm_id ? _shared_string_get(id->shm_id) : "");
        printf("LoadOpts: width          %d\n", id->opts.w);
        printf("          height         %d\n", id->opts.h);
        printf("          degree         %d\n", id->opts.degree);
        printf("          scale_down_by  %d\n", id->opts.scale_down_by);
        if (id->opts.dpi)
          printf("          dpi            %.2f\n", id->opts.dpi);
        else
          printf("          dpi            0\n");
        printf("          orientation    %s\n", id->opts.orientation ? "YES" : "NO");
        printf("          region         (%d,%d) %dx%d\n",
               id->opts.region.x, id->opts.region.y,
               id->opts.region.w, id->opts.region.h);

        switch (id->opts.scale_load.scale_hint)
          {
           case EVAS_IMAGE_SCALE_HINT_NONE:
             scale_hint = "EVAS_IMAGE_SCALE_HINT_NONE"; break;
           case EVAS_IMAGE_SCALE_HINT_DYNAMIC:
             scale_hint = "EVAS_IMAGE_SCALE_HINT_DYNAMIC"; break;
           case EVAS_IMAGE_SCALE_HINT_STATIC:
             scale_hint = "EVAS_IMAGE_SCALE_HINT_STATIC"; break;
           default:
             scale_hint = "<invalid>"; break;
          }

        printf("          scale src      (%d,%d) %dx%d\n",
               id->opts.scale_load.src_x, id->opts.scale_load.src_y,
               id->opts.scale_load.src_w, id->opts.scale_load.src_h);
        printf("          scale dst      %dx%d\n",
               id->opts.scale_load.dst_w, id->opts.scale_load.dst_h);
        printf("          scale smooth   %s\n",
               id->opts.scale_load.smooth ? "YES" : "NO");
        printf("          scale hint     %s (%d)\n",
               scale_hint, id->opts.scale_load.scale_hint);

        fd = (File_Data *)
              _shared_index_item_get_by_id(sf_files, sizeof(*fd), id->file_id);
        if (fd)
          {
             printf("File:     ID             %d\n", id->file_id);
             printf("          Path:Key:      '%s':'%s'\n",
                    _shared_string_get(fd->path), _shared_string_get(fd->key));
             printf("          Loader:        %s\n",
                    _shared_string_get(fd->loader_data));
             printf("          Geometry:      %dx%d\n", fd->w, fd->h);
             printf("          Animation:     anim: %s, frames: %d, loop: %d, hint: %d\n",
                    fd->animated ? "YES" : "NO",
                    fd->frame_count, fd->loop_count, fd->loop_hint);
             printf("          Alpha:         %s\n", fd->alpha ? "YES" : "NO");
             printf("          Changed:       %s\n", fd->changed ? "YES" : "NO");
          }
        else
          printf("File: ID %d not found\n", id->file_id);

        printf_newline(0);
     }

   printf("\n\n");
   fflush(stdout);
}

static void
_fonts_all_print_short(void)
{
   int k;

   static const char *rend_flags[] = { "R", "S", "W", "SW", "X" };

   if (!sf_fonts) return;

   printf("List of loaded fonts: %s\n", eina_file_filename_get(sf_fonts->f));
   printf("Rendering flags (RF): "
          "R: Regular, S: Slanted, W: Weight, X: Invalid\n\n");
   printf(" Index FontID Refcnt  Size   DPI RF  GlIdx GlData File[:Name]\n");
   printf_newline(0);

   for (k = 0; k < sf_fonts->header->count; k++)
     {
        Font_Data *fd;
        int rflag;
        const char *rf;

        fd = _shared_array_item_get(sf_fonts, k);
        if (!fd) break;
        if (!fd->id || !fd->refcount) continue;

        rflag = fd->rend_flags;
        if (rflag < 0 || rflag > 3) rflag = 4;
        rf = rend_flags[rflag];

        if (fd->name)
          printf("%6d %6d %6d %5d %5d %-2s %6d %6d '%s':'%s'\n",
                 k, fd->id, fd->refcount, fd->size, fd->dpi, rf,
                 fd->glyph_index_shm, fd->mempool_shm,
                 fd->file ? _shared_string_get(fd->file) : "",
                 _shared_string_get(fd->name));
        else
           printf("%6d %6d %6d %5d %5d %-2s %6d %6d '%s'\n",
                  k, fd->id, fd->refcount, fd->size, fd->dpi, rf,
                  fd->glyph_index_shm, fd->mempool_shm,
                  fd->file ? _shared_string_get(fd->file) : "");
     }

   printf_newline(1);
}

static void
_glyphs_all_print(Shm_File *sf)
{
   int k;
   int nglyphs = 0;
   int mem_used = 0;

   printf("  GlyphID Refcnt  Index  Size  Rows Width Pitch Grays H M  "
          "BufID Offset ShmPath\n");

   for (k = 0; k < sf->header->count; k++)
     {
        Glyph_Data *gd;

        gd = _shared_array_item_get(sf, k);
        if (!gd) break;
        if (!gd->id) continue;

        printf(" %8u %6u %6u %5u %5u %5u %5u %5u %1u %1u %6u %6u '%s'\n",
               gd->id, gd->refcount, gd->index, gd->size, gd->rows, gd->width,
               gd->pitch, gd->num_grays, gd->hint, gd->pixel_mode, gd->buffer_id,
               gd->offset, _shared_string_get(gd->mempool_id));

        nglyphs++;
        mem_used += gd->size;
     }

   printf("Total %d glyph(s) loaded, using %d bytes (w/o padding)\n",
          nglyphs, mem_used);
}

static void
_fonts_all_print_full(void)
{
   int k;

   static const char *rend_flags[] = { "R", "S", "W", "SW", "X" };

   if (!sf_fonts) return;

   printf("List of loaded fonts: %s\n", eina_file_filename_get(sf_fonts->f));
   printf("Rendering flags: "
          "R: Regular, S: Slanted, W: Weight, X: Invalid\n");
   printf("H: Hint, M: Pixel mode\n\n");
   printf_newline(0);

   for (k = 0; k < sf_fonts->header->count; k++)
     {
        Shm_File *sf;
        Font_Data *fd;
        int rflag;
        const char *rf;

        fd = _shared_array_item_get(sf_fonts, k);
        if (!fd) break;
        if (!fd->id) continue;
        if (!fd->glyph_index_shm) continue;

        sf = _shm_file_open(_shared_string_get(fd->glyph_index_shm));
        if (!_shm_file_probe(sf))
          {
             _shm_file_close(sf);
             continue;
          }

        rflag = fd->rend_flags;
        if (rflag < 0 || rflag > 3) rflag = 4;
        rf = rend_flags[rflag];

        printf("Font #%-8d %d\n", k, fd->id);
        printf("Refcount       %d\n", fd->refcount);
        printf("File           '%s'\n", _shared_string_get(fd->file));
        printf("Name           '%s'\n",
               fd->name ? _shared_string_get(fd->name) : "");
        printf("Size           %d\n", fd->size);
        printf("DPI            %d\n", fd->dpi);
        printf("Rendering flag %s (%d)\n", rf, fd->rend_flags);
        printf("Glyph index    '%s'\n", _shared_string_get(fd->glyph_index_shm));
        printf("Glyph data     '%s'\n", _shared_string_get(fd->mempool_shm));

        _glyphs_all_print(sf);

        _shm_file_close(sf);
        printf_newline(0);
     }

   printf("\n\n");
   fflush(stdout);
}


int
main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
{
   Eina_List *opened_sf = NULL;
   Eina_List *shmfiles = NULL, *l1, *l2;
   const char *shmfolder = SHM_FOLDER;
   Eina_Bool full = EINA_FALSE;
   Shm_File *sf;
   char *name;
   struct winsize w;

   if (isatty(STDOUT_FILENO))
     {
        if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0)
          _termsize = w.ws_col;
     }

   if (argc > 1)
     {
        if (!strcmp(argv[1], "-h"))
          {
             printf("Usage: %s [-f] [folder]\n", argv[0]);
             return 0;
          }
        else if (!strcmp(argv[1], "-f"))
          {
             full = EINA_TRUE;
             if (argc > 2)
               shmfolder = argv[2];
          }
        else
          shmfolder = argv[1];
     }

   eina_init();
   _evas_cserve2_shm_debug_log_dom = eina_log_domain_register
         ("evas_cserve2_shm_debug", EINA_COLOR_BLUE);

   shmfiles = _shm_files_list(shmfolder);
   if (!shmfiles)
     {
        WRN("No shm file was found in %s", shmfolder);
        goto finish;
     }

   DBG("Found %d files in %s", eina_list_count(shmfiles), shmfolder);

   // Look for strings index & mempool
   EINA_LIST_FOREACH_SAFE(shmfiles, l1, l2, name)
     {
        sf = _shm_file_open(name);
        if (!_shm_file_probe(sf))
          {
             shmfiles = eina_list_remove_list(shmfiles, l1);
             _shm_file_close(sf);
             free(name);
             continue;
          }

        if (!sf->tag)
          _shm_file_close(sf);
        else
          opened_sf = eina_list_append(opened_sf, sf);

        if (!!sf_strindex
            && !!sf_strpool
            && !!sf_fonts
            && !!sf_images
            && !!sf_files)
          break;
     }

   if (!sf_strindex || !sf_strpool)
     {
        ERR("Could not identify strings memory pool");
        goto finish;
     }

   _index_tables_summary_print();
   _strings_all_print(full);
   _files_all_print_short();
   if (full) _files_all_print_all();
   _images_all_print_short();
   if (full) _images_all_print_full();
   _fonts_all_print_short();
   if (full) _fonts_all_print_full();

finish:
   EINA_LIST_FREE(opened_sf, sf)
     _shm_file_close(sf);

   EINA_LIST_FREE(shmfiles, name)
     free(name);

   eina_shutdown();
   return 0;
}