Wie oft stellen sich User wie ich die Frage, wie weit der Compile ist bzw wieviel noch fehlt…

Im Gentoo‐Wiki habe ich folgenden C++ Lösungsansatz gefunden, welchen ich als eprogress.cpp ablege und schliesslich mit g++ compile (g++ eprogress.cpp ‑o eprogress):

#include <dirent .h>
#include “fcntl.h”
#include <string>
#include <fstream>
using namespace std;

#define srccount 5
#define objcount 2

int countfiles(char *path, int& todo, int& done);
int dft(char *name);
int findproc(char *name);

int main() {
  char *path, *action;
  char line[256];
  char *est;
  est = “”;
  int done = 0, todo = 0, percent = 0;
  path = “/usr/tmp/portage/”;
  struct dirent *entry;         //This structure will hold file information
  struct stat file_status;      //This structure will be used to query file status
  DIR *dir = opendir(path);     //This pointer references the directory stream

  //  printf(“Emerge Progress v4.20 C++:\n”);
  //Make sure we have a directory stream pointer
  if (!dir) { perror(“opendir failure”); exit(1); }
  chdir(path);

  while ( (entry = readdir(dir)) != NULL) {
    //Don’t bother with the .. and . directories
    if ((strcmp(entry->d_name, “.”) != 0) && (strcmp(entry->d_name, “..”) != 0)) {
      //Get the status info for the current file
      if (stat(entry->d_name, &file_status) == 0) {
        //Is this a directory, or a file?
        if (S_ISDIR(file_status.st_mode)) {
          strcpy(line,entry->d_name);
          strcat(line,”/work”);
          todo = 0; done = 0;

          if (countfiles(line,todo,done) == 1) { if (todo == 0) { percent=0; } else { percent=100 * done / todo; }
                if (done > todo) {
                        todo = done++;
                        est = “~”;
                percent=100 * done / todo;}

            //Is it running?
            if (findproc(entry->d_name) == 1) { action=“C”; } else { action=“X”; }
            printf(“  * [%s] %s: %d/%d –  %s%d%\n”,action,entry->d_name,done,todo,est,percent);
          }
          chdir(path);
        }
      }
    }
  }

  //Make sure we close the directory stream
  if (closedir(dir) == ‑1) { perror(“closedir failure”); exit(1); }
}

int countfiles(char *path, int& T, int& D) {
  int c = 0,res = 0;
  struct dirent *entry;
  struct stat file_status;
  DIR *dir = opendir(path);

  if (!dir) { return 0; }

  //Change directory to the given path
  chdir(path);

  //Loop through all files and directories
  while ( (entry = readdir(dir)) != NULL) {
    //Don’t bother with the .. and . directories
    if ((strcmp(entry->d_name, “.”) != 0) && (strcmp(entry->d_name, “..”) != 0)) {
      //Get the status info for the current file
      if (stat(entry->d_name, &file_status) == 0) {
        //Is this a directory, or a file?
        if (S_ISDIR(file_status.st_mode)) {
          //Call countfiles again (recursion) and add the result to the count total
          countfiles(entry->d_name,T,D);
          chdir(“..”);
        } else {
          //We’ve found a file, increment the count
          res=dft(entry->d_name);
          if (res==1) { T=T+1; } else if (res==2) { D=D+1; }
        }
      }
    }
  }

  //Make sure we close the directory stream
  if (closedir(dir) == ‑1) { perror(“closedir failure”); exit(1); }

  //Return the file count
  return 1;
}

int dft(char *name)
{
  //Find out file type..
  //0= none
  //1= todo
  //2= done
  int c;
  char * tmp;
  char *src[] = {“.c/”,”.cpp/”,”.C/”,”.java/”,”.cc/”};
  char *obj[] = {“.o/”,”.class/”};

   strcpy(tmp,name);
   strcat(tmp,”/”);
   for(c=0; c<srccount ;++c){ if (strstr(tmp,src[c]) !=NULL) { return 1; } }
   for(c=0; c<objcount;++c){ if (strstr(tmp,obj[c]) !=NULL) { return 2; } }

   //Neither
   return 0;
}

int findproc(char *name)
{
  //Find the proc of portage
  int c = 0;
  char *res;
  char *path, *tmp;
  char buffer[256];
  path = “/proc/”;
  struct dirent *entry;
  struct stat file_status;
  DIR *dir = opendir(path);

  if (!dir) { return 0; }

  //Change directory to the given path
  chdir(path);

  //Loop through all files and directories
  while ( (entry = readdir(dir)) != NULL) {
    //Don’t bother with the .. and . directories
    if ((strcmp(entry->d_name, “.”) != 0) && (strcmp(entry->d_name, “..”) != 0)) {
      //Get the status info for the current file
      if (stat(entry->d_name, &file_status) == 0) {
        //Is this a directory, or a file?
        if (S_ISDIR(file_status.st_mode)) {

          chdir(entry->d_name);

          ifstream rfile (“cmdline”);
          if (rfile.is_open()) {
            rfile.getline (buffer,100);

            if (strstr(buffer,name) != NULL) { return 1; }
          }
          rfile.close();
          chdir(“..”);

        }
      }
    }
  }

  //Make sure we close the directory stream
  if (closedir(dir) == ‑1) { perror(“closedir failure”); exit(1); }

  //Return the file count
  return 0;
}

Dieses Programm zählt die vorhandenen Source‐Dateien und vergleicht sie mit der Anzahl der schon compilierten .o‑Files – dies ermöglicht uns eine Schätzung, wie weit das aktuelle Programm compiled ist;

So weit so gut – das Programm mit watch aufgerufen aktualisiert den Output periodisch bis es schliesslich mit STRG + C abgebrochen wird.

Komfort und Tuning: Für Leute wie mich, die inzwischen auch schon Xorg erobert haben und sich bis zu einem Desktop vorgewagt haben, bietet sich die Verwendung von xosd an:

eprogress | osd_cat –font=”-adobe-helvetica-bold-*-*-*-24-*-*-*-*-*-*-*” ‑c “#33CC33” ‑A right ‑o 60 ‑i 50 ‑d 3

… was uns einen kleinen Schriftzug mit dem aktuellen Emerge (falls laufend) in die rechte obere Ecke des Bildschirms zaubert, welcher nach 3 Sekunden wieder verschwindet. Ein kleines Bash‐Script mit einer Schleife lässt den Schriftzug immer wieder aufflackern, was ich persönlich als störend empfinde. Mein Workaround sieht wie folgt aus:

#!/bin/bash
while true; do
  eprogress | osd_cat –font=”-adobe-helvetica-bold-*-*-*-24-*-*-*-*-*-*-*” ‑c “#33CC33” ‑A right ‑o 60 ‑i 50 ‑d 3 &
  sleep 2.7s
done

Xosd_cat wird in den Hintergrund versetzt und alle 2,7 Sekunden aufgerufen. Da eprogress eine gewisse Zeit benötigt bis es seinen Job erledigt hat und die Ausgabe weitergegeben wird liegen die beiden Schriftzüge für einen Sekundenbruchteil übereinander und es entsteht der Effekt von verschwimmenden Zahlen. Da der Rest der Ausgabe statisch ist, merkt man dort keinen Unterschied.

Probleme:

  • Das Script muss Zugriff auf die Portage‐Verzeichnisse haben. Root?
  • Die Ausführung benötigt eine Verbindung zu einem X‑Server

Ich bin natürlich nicht böse wenn jemand die komplette Prozedur in C implementiert und als Hintergrunddienst zur Verfügung stellt…

Vorheriger Beitrag Nächster Beitrag