Subversion Repositories SvarDOS

Rev

Rev 1965 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
219 mateuszvis 1
/*
268 mateuszvis 2
 * This file is part of the pkg (SvarDOS) project.
1678 mateusz.vi 3
 * Copyright (C) Mateusz Viste 2012-2024
219 mateuszvis 4
 */
5
 
6
#include <ctype.h>    /* toupper() */
7
#include <stdio.h>
8
#include <string.h>    /* strlen() */
2235 bernd.boec 9
#include <strings.h>
219 mateuszvis 10
#include <stdlib.h>    /* free() */
11
#include <unistd.h>    /* rmdir(), unlink() */
12
#include <direct.h>  /* watcom needs this for the rmdir() prototype */
13
 
14
#include "helpers.h"   /* slash2backslash() */
2235 bernd.boec 15
#include "svarlang.lib/svarlang.h"
253 mateuszvis 16
 
219 mateuszvis 17
#include "pkgrem.h"
18
 
19
 
20
struct dirliststruct {
21
  struct dirliststruct *next;
22
  char dirname[2]; /* this must be the last item in the structure */
23
};
24
 
25
 
26
/* adds a directory to dirlist, if not already present */
235 mateuszvis 27
static struct dirliststruct *rememberdir(struct dirliststruct *dirlist, const char *path) {
219 mateuszvis 28
  struct dirliststruct *res;
29
  /* if already present, do nothing */
30
  for (res = dirlist; res != NULL; res = res->next) {
31
    if (strcasecmp(res->dirname, path) == 0) return(dirlist);
32
  }
33
  /* not in the list yet - add it */
34
  res = malloc(sizeof(struct dirliststruct) + strlen(path));
35
  if (res == NULL) {  /* out of memory */
1965 mateusz.vi 36
    outputnl(svarlang_str(2,14)); /* "Out of memory!" */
219 mateuszvis 37
    return(NULL);
38
  }
39
  strcpy(res->dirname, path);
40
  res->next = dirlist;
41
  return(res);
42
}
43
 
44
 
45
/* explode a path into subdirectories, and remember each one inside dirlist */
46
static struct dirliststruct *rememberpath(struct dirliststruct *dirlist, char *path) {
47
  int x, gameover = 0;
48
  /* iterate on the path, and add each subdirectory */
49
  for (x = 0;; x++) {
50
    switch (path[x]) {
51
      case 0:
52
        gameover = 1;
53
      case '/':
54
      case '\\':
55
        path[x] = 0;
56
        dirlist = rememberdir(dirlist, path);
57
        path[x] = '\\';
58
    }
59
    if (gameover != 0) break;
60
  }
61
  return(dirlist);
62
}
63
 
64
 
65
/* removes a package from the system. Returns 0 on success, non-zero otherwise */
235 mateuszvis 66
int pkgrem(const char *pkgname, const char *dosdir) {
67
  char fpath[256];
253 mateuszvis 68
  char buff[256];
219 mateuszvis 69
  FILE *flist;
70
  int lastdirsep;
71
  struct dirliststruct *dirlist = NULL; /* used to remember directories to remove */
72
 
1678 mateusz.vi 73
  /* open the (legacy) listing file at %DOSDIR%\packages\pkgname.lst
74
   * if not exists then fall back to appinfo\pkgname.lsm */
219 mateuszvis 75
  sprintf(fpath, "%s\\packages\\%s.lst", dosdir, pkgname);
253 mateuszvis 76
  flist = fopen(fpath, "rb");
77
  if (flist == NULL) {
1678 mateusz.vi 78
    sprintf(fpath, "%s\\appinfo\\%s.lsm", dosdir, pkgname);
79
    flist = fopen(fpath, "rb");
80
    if (flist == NULL) {
1965 mateusz.vi 81
      /* "Package %s is not installed, so not removed" */
82
      sprintf(buff, svarlang_str(4,0), pkgname);
83
      outputnl(buff);
1678 mateusz.vi 84
      return(-1);
85
    }
219 mateuszvis 86
  }
87
 
1678 mateusz.vi 88
  /* remove all files/folders listed in pkgname.lsm but NOT pkgname.lsm */
253 mateuszvis 89
  while (freadtokval(flist, buff, sizeof(buff), NULL, 0) == 0) {
90
    int x;
219 mateuszvis 91
 
1678 mateusz.vi 92
    /* skip empty lines */
93
    if (buff[0] == 0) continue;
94
 
95
    /* change all slash to backslash */
96
    slash2backslash(buff);
97
 
98
    /* skip garbage */
99
    if ((buff[1] != ':') || (buff[2] != '\\')) continue;
100
 
101
    /* trim out CRC information (if present) */
102
    trimfnamecrc(buff);
103
 
219 mateuszvis 104
    /* remember the path part for removal later */
105
    lastdirsep = -1;
253 mateuszvis 106
    for (x = 1; buff[x] != 0; x++) {
107
      if ((buff[x] == '\\') && (buff[x - 1] != ':')) lastdirsep = x;
219 mateuszvis 108
    }
109
    if (lastdirsep > 0) {
253 mateuszvis 110
      buff[lastdirsep] = 0;
111
      dirlist = rememberpath(dirlist, buff);
112
      buff[lastdirsep] = '\\';
219 mateuszvis 113
    }
253 mateuszvis 114
 
219 mateuszvis 115
    /* if it's a directory, skip it */
253 mateuszvis 116
    if (buff[strlen(buff) - 1] == '\\') continue;
117
 
1678 mateusz.vi 118
    /* do not delete pkgname.lst at this point because I am using it (will be
119
     * deleted later) */
253 mateuszvis 120
    if (strcasecmp(buff, fpath) == 0) continue;
121
 
122
    /* remove it */
1965 mateusz.vi 123
    output(svarlang_str(4,4)); /* removing */
124
    output(" ");
125
    outputnl(buff);
253 mateuszvis 126
    unlink(buff);
219 mateuszvis 127
  }
128
 
1678 mateusz.vi 129
  /* close the lsm file */
219 mateuszvis 130
  fclose(flist);
131
 
253 mateuszvis 132
  /* iterate over dirlist and remove directories if empty, from longest to shortest */
219 mateuszvis 133
  while (dirlist != NULL) {
134
    struct dirliststruct *dirlistpos, *previousdir;
135
    /* find the longest path, and put it on top */
136
    previousdir = dirlist;
137
    for (dirlistpos = dirlist->next; dirlistpos != NULL; dirlistpos = dirlistpos->next) {
138
      if (strlen(dirlistpos->dirname) > strlen(dirlist->dirname)) {
139
        previousdir->next = dirlistpos->next;
140
        dirlistpos->next = dirlist;
141
        dirlist = dirlistpos;
142
        dirlistpos = previousdir;
143
      } else {
144
        previousdir = dirlistpos;
145
      }
146
    }
253 mateuszvis 147
    /* printf("RMDIR %s\n", dirlist->dirname); */
148
    rmdir(dirlist->dirname);
219 mateuszvis 149
    /* free the allocated memory for this entry */
150
    dirlistpos = dirlist;
151
    dirlist = dirlistpos->next;
152
    free(dirlistpos);
153
  }
154
 
253 mateuszvis 155
  /* remove the lst file */
1965 mateusz.vi 156
  output(svarlang_str(4,4)); /* "removing" */
157
  output(" ");
158
  outputnl(fpath);
219 mateuszvis 159
  unlink(fpath);
1678 mateusz.vi 160
 
1965 mateusz.vi 161
  sprintf(buff, svarlang_str(4,5), pkgname); /* "Package %s has been removed." */
162
  outputnl(buff);
219 mateuszvis 163
  return(0);
164
}