Logo Search packages:      
Sourcecode: deborphan version File versions  Download package

keep.c

/* keep.c - Maintain a list of packages to keep for deborphan.
   Copyright (C) 2000, 2001, 2002, 2003 Cris van Pelt
   Copyright (C) 2003, 2004 Peter Palfrader

   $Id: keep.c 409 2004-04-21 12:20:43Z weasel $

   Distributed under the terms of the Artistic License.

   The general idea was borrowed from Wessel Danker's debfoster program.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <deborphan.h>
#include <xalloc.h>

/* If package is a valid package, this function returns 0. On error, it
 * returns -1, if it is not a valid package, it returns the position in
 * the 'args' list +1.
 */
int
pkggrep(const char *sfile, char **pkgnames)
{
    FILE *fp;
    char *s, *t = NULL;
    int i = 0;
    s = (char *) xmalloc (200);

    if (!(fp = fopen(sfile, "r")))
      return -1;

    while (*pkgnames) {
      t = (char *) xmalloc (9+strlen(*pkgnames));
      rewind(fp);

      strcpy(t, "ackage:");
      strcat(t, *pkgnames);
      strcat(t, "\n");
    
      while (fgets(s, 200, fp)) {
          if (upcase(*s) != 'P')
            continue;

          strstripchr(s, ' ');
          if (strcmp(s+1, t) == 0) {
            free(s);
            free(t);
            return 0;
          }
      }

      i++;
      pkgnames++;
    }

    free(s);
    free(t);
    return i;
}

/* Read the entire keep file into memory as an array of `dep's.
 */
dep *
readkeep(const char *kfile)
{
#ifdef LOW_MEM
    FILE *f;
#else
    char *f, *bak;
#endif
    char *line, *line2;
    dep *d, *ret;
    int i = 1;

    d = ret = xmalloc(10 * sizeof(dep));

    if (!(f = debopen(kfile)))
      return NULL;

#ifndef LOW_MEM
    bak = f;
#endif

    while ((line = nextline(&f))) {
      /* We'll be modifying line with strstripchr, which nextline does
       * not like. Guess that's the price of speed.
       */
      line2 = xstrdup(line);

      strstripchr(line2, '\n');

      d->name = line2;
      d->namehash = strhash(d->name);

      d++;
      i++;
      if (i % 10 == 0) {
          ret = xrealloc(ret, (i+10) * sizeof(dep));
          d = ret + i - 1;
      }
    }
    d->name = NULL;

#ifdef LOW_MEM
    fclose(f);
    free(line);
#else
    free(bak);
#endif
    return ret;
}

int
mustkeep(const dep d)
{
    dep *c;

    for (c = keep; c && c->name; c++) {
      if (pkgcmp(*c, d))
          return 1;
    }

    return 0;
}

int
addkeep(const char *kfile, char **add)
{
    FILE *fd;
    int i = 0;

    if (!(fd = fopen(kfile, "a+")))
      return -1;

    while (*add) {
      if (**add && **add != '\n') {
          fputs(*add, fd);
          fputc('\n', fd);
      }
      add++;
      i++;
    }

    return i;
}

/* Sure, this function will never win the Function of the Year award, but
 * at least we got rid of the temporary files. Now all I/O is done in
 * memory.
 */
int
delkeep(const char *kfile, char **del)
{
    int fd, i, cnt, j, shrunk = 0;
    struct stat sbuf;
    char *fcont, *tok, *pt, *orig;
    size_t len;

    if ((fd = open(kfile, O_RDONLY | O_CREAT, 0666 /* let umask handle -w */ )) < 0)
      return -1;

    if (fstat(fd, &sbuf) < 0)
      return -1;

    for (cnt = 0; del[cnt]; cnt++)
      ;

    orig = fcont = xmalloc(sbuf.st_size);
    
    if (read(fd, fcont, sbuf.st_size) < sbuf.st_size) {
      free(fcont);
      close(fd);
      return -1;
    } 

    while ((tok = sstrsep(&fcont, '\n'))) {
      for (i = 0; i < cnt; i++) {
          if (strcmp(del[i], tok) == 0) {
            pt = fcont - (strlen(tok)+1);
            shrunk += (strlen(tok)+1);

            for (j = 0; *(fcont + j); j++)
                *(pt + j) = *(fcont + j);
          }
      }
      free(tok);
    }
    close(fd);
    len = sbuf.st_size - shrunk;

    if ((fd = open(kfile, O_WRONLY | O_TRUNC)) < 0) {
      free(orig);
      return -1;
    }
    
    if (write(fd, orig, len) < len) {
      free(orig);
      return -1;
    }
    
    return 0;
}

/* If something in list is found in keep, this function returns its 
 * position in the list +1, else it returns 0.
 */
unsigned int
hasduplicate(char **list)
{
    unsigned int i;
    dep d;

    for (i = 0; list[i]; i++) {
      d.name = list[i];
      d.namehash = strhash(list[i]);
      if (mustkeep(d))
          return i+1;
    }

    return 0;
}

dep *
mergekeep(const dep *a, const dep *b)
{
    unsigned int i = 0, j = 0, x = 0, y = 0;
    dep *ret;

    if (!(a || b))
      return NULL;

    if (a)
      while (a[i++].name);
    if (b)
      while (b[j++].name);

    ret = (dep *) xmalloc (sizeof(dep) * (j+i));

    for (i = 0; a && a[i].name; i++)
      ret[i] = a[i];

    for (j = 0; b && b[j].name; j++) {
      for (x = 0, y = 0; ret[x].name; x++) {
          if (pkgcmp(ret[x], b[j]))
            y = 1;
      }
      if (!y)
          ret[i++] = b[j];
    }

    return ret;
}

int
listkeep(const char *kfile)
{
    FILE *fp = fopen(kfile, "r");
    char s[100];

    if (!fp)
      return 0;

    while (fgets(s, 100, fp)) {
      if (*s != '\n')
          printf("%s", s);
    }

    return 1;
}

/* This function handles the arguments to --add-keep and --del-keep.
 */
char **
parseargs(int argind, int argc, char **argv)
{
    char **ret = xcalloc(50, sizeof(char *));
    char t[100];
    int i = 0, s = 50;
    
    while (argind < argc) {
      if (*argv[argind] == '-' && *(argv[argind]+1) == '\0') {
          while (fgets(t, 100, stdin)) {
            if (i == s) {
                s *= 2;
                ret = xrealloc(ret, s * sizeof(char *));
            }
            /* Allocate an extra byte, just to be on the safe side. */
            ret[i] = (char *) xmalloc((strlen(t)+1));
            strstripchr(t, ' ');
            strstripchr(t, '\r');
            strstripchr(t, '\n');
            strcpy(ret[i++], t);
          }
          argind++;
          continue;
      }
      ret[i] = xstrdup(argv[argind]);
      argind++;
      i++;
    }

    return ret;
}

Generated by  Doxygen 1.6.0   Back to index