home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFILEMAN / XFILEMAN.TAR / xfilemanager / dir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-24  |  8.3 KB  |  360 lines

  1. /*
  2.  * Copyright 1993 by Ove Kalkan, Cremlingen, Germany
  3.  *
  4.  * Permission to use, copy, modify, distribute and sell this software and it's
  5.  * documentation for any purpose is hereby granted without fee, rpovided that
  6.  * the above copyright notice and this permission appear in supporting
  7.  * documentation, and that the name of Ove Kalkan not to be used in
  8.  * advertising or publicity pertaining to distributiopn of the software without
  9.  * specific, written prior permission. Ove Kalkan makes no representations
  10.  * about the suitability of this software for any purpose. It is provided
  11.  * as is without express or implied warranty.
  12.  *
  13.  * OVE KALKAN DISPLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  14.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS, IN NO
  15.  * EVENT SHALL OVE KALKAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  16.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  17.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  18.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  19.  * PERFORMANCE OF THIS SOFTWARE.
  20.  *
  21.  * $Header: filename,v 1.0 yyyy/mm/dd hh:mm:ss loginname Exp $
  22.  */
  23.  
  24. #include "global.h"
  25.  
  26. /*
  27.  * Global variables
  28.  */
  29.  
  30. /*
  31. **    Function name : fillDir
  32. **
  33. **    Description : Fuellen einer Dir-Struktur
  34. **    Input : zeiger auf den Dirglyph, dessem Unterdirectories untersucht werden sollen
  35. **    Ouput :
  36. */
  37. void fillDir (Dir_Glyph *dir)
  38. {
  39.     String        dir_path;    /* Hier wird der vollstaendige Pfad des Directories
  40.                        stehen */
  41.     DIR        *dir_ptr;    /* Zeiger auf die Dir-Structur */
  42.     struct    dirent    *d_ent;        /* Direntry */
  43.     char        s_buf[1024];
  44.  
  45.     /*
  46.      * Wenn dem Dir-Glyph noch eine Dir-Liste zugeordnet ist, dann
  47.      * diese loesche
  48.      */
  49.     if (dir->dir_count > 0) {
  50.         int    i;
  51.  
  52. /*        for (i = 0; i < dir->dir_count; i++)
  53.             if (dir->dir[i]) {
  54.                 if (dir->dir[i]->name)
  55.                     free(dir->dir[i]->name);
  56.                 free(dir->dir[i]);
  57.             }
  58. */        dir->dir_count = 0;
  59.     }
  60.  
  61.     /*
  62.      * Den vollstaendigen Pfadnamen holen
  63.      */
  64.     dir_path = getPath (dir);
  65.  
  66.     /*
  67.      * Das Dir oeffnen und die Eintraege auslesen
  68.      */
  69.     if (!(dir->flags & DIR_READABLE) || !(dir_ptr = opendir (dir_path))) {
  70.         dir->flags &= (~DIR_READABLE);
  71.         return;        /* Abbruch da nicht geoeffnet */
  72.     }
  73.  
  74.     /*
  75.      * Dir-Open flag setzen
  76.      */
  77.     dir->open = TRUE;
  78.  
  79.     /*
  80.      * Directory auslesen
  81.      */
  82.     while ((d_ent = readdir(dir_ptr))) {
  83.         struct stat    buf;
  84.  
  85.         /*
  86.          * Den vollen Pfadnamen des Direntries erzeugen
  87.          */
  88.         sprintf (s_buf,"%s%s%s\0", dir_path,
  89.                        (dir_path[1] == '\0' ? "" : "/"),
  90.                        d_ent->d_name);
  91.  
  92.         /*
  93.          * Den Status des Files holen
  94.          */
  95.         (void) stat (s_buf, &buf);
  96.  
  97.         /*
  98.          * Ueberpruefen ob der Eintrag ein Directory und nicht . oder .. ist
  99.          */
  100.         if (S_ISDIR(buf.st_mode) && strcmp(d_ent->d_name,".")
  101.             && strcmp(d_ent->d_name,"..")) {
  102.             /*
  103.              * Da dir, Dir_Glyph um einen Eintrag erweitern
  104.              */
  105.             Dir_Glyph    *new_dir;
  106.  
  107.             /*
  108.              * Liste im Glyph um einen Eintrag erweitern
  109.              */
  110.             (dir->dir_count)++;
  111.             if (!dir->dir) {
  112.                 if (!(dir->dir = (Dir_Glyph **) malloc (sizeof(Dir_Glyph *))))
  113.                     FATAL_ERROR ("fillDir: Reallocating Dirlist failed\n");
  114.             }
  115.             else {
  116.                 if (!(dir->dir = (Dir_Glyph **) realloc ((void *) dir->dir,
  117.                                     sizeof(Dir_Glyph *)*dir->dir_count)))
  118.                     FATAL_ERROR ("fillDir: Reallocating Dirlist failed\n");
  119.             }
  120.             if (!(new_dir = (Dir_Glyph *) malloc(sizeof(Dir_Glyph))))
  121.                 FATAL_ERROR ("fillDir: Allocating new Glyph failed\n");
  122.  
  123.             /*
  124.              * Den neuen Glyph als leer initialisieren
  125.              */
  126.             new_dir->dir_count = 0;
  127.             new_dir->dir = NULL;
  128.             new_dir->x = 0;
  129.             new_dir->y = 0;
  130.             new_dir->parent = dir;
  131.             new_dir->open = FALSE;
  132.             new_dir->link = NULL;
  133.  
  134.             /*
  135.              * Den Namen des Glyphs initialisieren
  136.              */
  137.             if (!(new_dir->name = (String) malloc(strlen(d_ent->d_name)+1)))
  138.                 FATAL_ERROR ("fillDir: Allocating Name for new Glyph failed\n");
  139.  
  140.             strncpy(new_dir->name,d_ent->d_name,strlen(d_ent->d_name));
  141.             new_dir->name[strlen(d_ent->d_name)] = '\0';
  142.  
  143.             /*
  144.              * Den Status neuen Dirs bestimmen
  145.              */
  146.             new_dir->flags = getFlags(&buf);
  147.  
  148.             /*
  149.              * Ueberpruefen ob Link
  150.              */
  151. #ifndef COHERENT
  152.             (void) lstat (s_buf, &buf);
  153.             new_dir->flags |= (S_ISLNK(buf.st_mode) ? DIR_LINK : 0);
  154.             if (new_dir->flags & DIR_LINK) {
  155.                 char    buf[255];
  156.                 int    j;
  157.  
  158.                 if ((j = readlink(s_buf,buf,254)) > 0) {
  159.                     buf[j++] = '\0';
  160.                     new_dir->link = (char *) malloc(j);
  161.                     if (!(new_dir->link))
  162.                         FATAL_ERROR("dir.c: malloc failed.");
  163.                     sprintf(new_dir->link,"%s\0",buf);
  164.                 }
  165.             }
  166.             dir->dir[dir->dir_count-1] = new_dir;
  167. #endif
  168.         }
  169.     }
  170.     closedir (dir_ptr);
  171.     free (dir_path);
  172.  
  173.     /*
  174.      * Die Directoryeintraege aplhabetisch sortieren falls moeglich
  175.      */
  176.     if (dir->dir_count > 1) {
  177.         int    i, j;
  178.  
  179.         for (i = 0; i < dir->dir_count - 1; i++) {
  180.             for (j = 1; j < dir->dir_count - i; j++) {
  181.                 if (compareGlyph(dir->dir[j-1],dir->dir[j]) == 1) {
  182.                     Dir_Glyph *dummy = dir->dir[j];
  183.  
  184.                     dir->dir[j] = dir->dir[j-1];
  185.                     dir->dir[j-1] = dummy;
  186.                 }
  187.             }
  188.         }
  189.     }
  190. }
  191.  
  192.  
  193.  
  194. /*
  195. **    Function name : compareGlyph
  196. **
  197. **    Description : Vergleichsfunktion fuer QSort 
  198. **    Input : die zwei obligatorischen Zeiger auf die Elemente
  199. **    Ouput : -1 falls a < b, 0 fall a == b oder 1 fall a > b
  200. */
  201. int compareGlyph (Dir_Glyph *da, Dir_Glyph *db)
  202. {
  203.     int    i;
  204.     char    *a = da->name,
  205.         *b = db->name;
  206.  
  207.     i = (strlen(a) > strlen(b) ? strlen(b) : strlen(a));
  208.     while (i--) {
  209.         if (*a > *b) {
  210.             return(1);
  211.         }
  212.         else if (*a < *b) {
  213.             return(-1);
  214.         }
  215.         a++;
  216.         b++;
  217.     }
  218.     if (strlen(da->name) > strlen(db->name)) {
  219.         return(1);
  220.     }
  221.     if (strlen(da->name) < strlen(db->name)) {
  222.         return(-1);
  223.     }
  224.     return(0);
  225. }
  226.  
  227.  
  228.  
  229. /*
  230. **    Function name : showDir
  231. **
  232. **    Description : Anzeigen eines Directorybaumes im Fenster
  233. **    Input : Zeiger auf das Fensterwidget und den Dir_glyph
  234. **    Ouput : Liefert den Y-Wert des letzen Dir-Glyphs im Baum zurueck
  235. */
  236. void showDir (Widget window, Dir_Glyph *dir,
  237.            Dimension x, Dimension y,
  238.            Dimension *lx, Dimension *ly,
  239.            Dimension hs, Dimension he)
  240. {
  241.     Dimension    py;
  242.     int        i;
  243.     Boolean        b;
  244.  
  245.     /*
  246.      * Position des Icons fuer das Dir_Glyph festlegen
  247.      */
  248.     dir->x = x;
  249.     dir->y = y;
  250.  
  251.     /*
  252.      * Icon ausgeben und Dirlabel zeichnen
  253.      */
  254.     if (y >= hs && y <= he) {
  255.         b = (selc_g == dir ? TRUE : FALSE);
  256.         drawDir (dir_area, dir, b, b);
  257.     }
  258.  
  259.     if (dir->x + 24 + 8*strlen(dir->name) > *lx)
  260.         *lx = dir->x + 24 + 8*(strlen(dir->name)+strlen(dir->link));
  261.  
  262.     /*
  263.      * Alle Unterdirectories zeichnen fall Directory offen
  264.      */
  265.     *ly = py = y;
  266.     if (dir->open && dir->dir_count > 0) {
  267.         for (i = 0; i < dir->dir_count; i++) {
  268.             /*
  269.              * Die Pfadlinie ziehen
  270.              */
  271.             XDrawLine (XtDisplay(dir_area), XtWindow(dir_area),
  272.                    line_gc, x + 8, *ly + DIR_Y_STEP + 8,
  273.                    x + DIR_X_STEP - 10,
  274.                    *ly + DIR_Y_STEP + 8);
  275.             showDir(window,dir->dir[i],x + DIR_X_STEP,
  276.                 *ly + DIR_Y_STEP, lx, ly, hs, he);
  277.         }
  278.         XDrawLine (XtDisplay(dir_area), XtWindow(dir_area),
  279.                line_gc, x + 8, py + 19,
  280.                     x + 8, dir->dir[i-1]->y + 8);
  281.     }
  282. }
  283.  
  284.  
  285.  
  286.  
  287. /*
  288. **    Function name : getPath
  289. **
  290. **    Description : Generieren des Vollstaendigen Pfadnamens aus einem Glyph - rekurziv
  291. **    Input : Zeiger auf den entsprechenden Dir_Glyph
  292. **    Ouput : Zeiger auf den String mit dem Pfadnamen
  293. */
  294. String getPath (Dir_Glyph *dir)
  295. {
  296.     String    back,        /* Wird zurueck geliefert */
  297.         got;        /* kommt vom Parent */
  298.     
  299.     /*
  300.      * Wenn Parentdir, dann Pfad davon holen
  301.      */
  302.     if (dir->parent)
  303.         got = getPath(dir->parent);
  304.     else
  305.         got = "\0";
  306.  
  307.     /*
  308.      * Stringlaenge fuer back besorgen
  309.      */
  310.     if (!(back = (String) malloc(strlen(got) + strlen(dir->name) + 2)))
  311.         FATAL_ERROR("getPath: Cannot allocate Memory\n");
  312.  
  313.     /*
  314.      * Die Teilstrings verknuepfen
  315.      */
  316.     if (!strcmp("/",got))
  317.         sprintf(back,"/%s",dir->name);
  318.  
  319.     else if (*got != '\0')
  320.         sprintf(back,"%s/%s\0",got,dir->name);
  321.     else
  322.         sprintf(back,"%s",dir->name);
  323.  
  324.     /*
  325.      * Got wieder Freigeben falls nicht "\0"
  326.      */
  327.     if (*got != '\0')
  328.         free(got);
  329.  
  330.     /*
  331.      * Den vollstaendigen Pfad zurueckliefern
  332.      */
  333.     return(back);
  334. }
  335.  
  336.  
  337.  
  338. /*
  339.  * die File-Flags bestimmen
  340.  */
  341. int    getFlags (struct stat *buf)
  342. {
  343.     uid_t        uid = getuid();
  344.     gid_t        gid = getgid();
  345.  
  346.     int        b = 0;
  347.  
  348.     if (uid == 0)        /* Root darf alles */
  349.         return (DIR_READABLE + DIR_WRITEABLE);
  350.  
  351.     /* Das scheint noch nicht ganz zu funktionieren, muss verbessert werden */
  352.     b |= ((uid == buf->st_uid && S_IRUSR&buf->st_mode) | 
  353.           (gid == buf->st_gid && S_IRGRP&buf->st_mode) |
  354.            S_IRGRP&buf->st_mode) ? DIR_READABLE : 0;
  355.  
  356.     b |= ((uid == buf->st_uid && S_IWUSR&buf->st_mode) | 
  357.           (gid == buf->st_gid && S_IWGRP&buf->st_mode) |
  358.            S_IWGRP&buf->st_mode) ? DIR_WRITEABLE : 0;
  359.     return (b);
  360. }