Subversion Repositories SvarDOS

Rev

Rev 252 | Rev 256 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 252 Rev 255
1
/*
1
/*
2
 * This file is part of pkginst
2
 * This file is part of pkginst
3
 * Copyright (C) 2012-2021 Mateusz Viste
3
 * Copyright (C) 2012-2021 Mateusz Viste
4
 *
4
 *
5
 * It contains a few helper function...
5
 * It contains a few helper function...
6
 */
6
 */
7
 
7
 
8
 
8
 
9
#include <ctype.h>    /* tolower() */
9
#include <ctype.h>    /* tolower() */
10
#include <direct.h>   /* provides the mkdir() prototype */
10
#include <direct.h>   /* provides the mkdir() prototype */
11
#include <string.h>   /* */
11
#include <string.h>   /* */
12
#include <stdio.h>    /* sprintf() */
12
#include <stdio.h>    /* sprintf() */
13
#include <stdlib.h>   /* atoi() */
13
#include <stdlib.h>   /* atoi() */
14
#include <sys/stat.h> /* mkdir() */
14
#include <sys/stat.h> /* mkdir() */
15
 
15
 
16
#include "rtrim.h"
16
#include "rtrim.h"
17
#include "helpers.h"
17
#include "helpers.h"
18
 
18
 
19
 
19
 
20
/* translates a version string into a array of integer values. The array must be 8-position long.
-
 
21
   returns 0 if parsing was successful, non-zero otherwise.
-
 
22
   Accepted formats follow:
-
 
23
    300.12.1
-
 
24
    1
-
 
25
    12.2.34.2-4.5
-
 
26
    1.2c
-
 
27
    1.01
-
 
28
    2013-12-31   */
-
 
29
static int versiontointarr(char *verstr, int *arr) {
-
 
30
  int i, vlen, dotcounter = 1, firstcharaftersep = 0;
-
 
31
  char *digits[8];
-
 
32
  char verstrcopy[16];
-
 
33
 
-
 
34
  /* fill the array with zeroes first */
-
 
35
  for (i = 0; i < 8; i++) arr[i] = 0;
-
 
36
 
-
 
37
  /* first extensively validate the input */
-
 
38
  if (verstr == NULL) return(-1);
-
 
39
  vlen = strlen(verstr);
-
 
40
  if (vlen == 0) return(-1);
-
 
41
  if (vlen > 15) return(-1);
-
 
42
  if ((verstr[0] < '0') || (verstr[0] > '9')) return(-1); /* a version string must start with a 0..9 digit */
-
 
43
  if ((tolower(verstr[vlen - 1]) >= 'a') && (tolower(verstr[vlen - 1]) <= 'z') && (vlen > 1)) { /* remove any letter from the end, and use it as a (very) minor differenciator */
-
 
44
    vlen -= 1;
-
 
45
    arr[7] = tolower(verstr[vlen]);
-
 
46
  }
-
 
47
  if ((verstr[vlen - 1] < '0') || (verstr[vlen - 1] > '9')) return(-1); /* a version string must end with a 0..9 digit */
-
 
48
 
-
 
49
  digits[0] = verstrcopy;
-
 
50
  for (i = 0; i < vlen; i++) {
-
 
51
    verstrcopy[i] = verstr[i];
-
 
52
    switch (verstr[i]) {
-
 
53
      case '.':
-
 
54
      case '-':
-
 
55
        if (i == 0) return(-1);
-
 
56
        if (verstrcopy[i-1] == 0) return(-1); /* do not allow two separators in a row */
-
 
57
        if (dotcounter > 6) return(-1);
-
 
58
        digits[dotcounter++] = &verstrcopy[i + 1];
-
 
59
        verstrcopy[i] = 0;
-
 
60
        firstcharaftersep = 1;
-
 
61
        break;
-
 
62
      case '0':
-
 
63
        /* if this is a zero right after a separator, and trailed with a digit
-
 
64
         * (as in '1.01'), then enforce a separator first */
-
 
65
        if ((firstcharaftersep != 0) && (verstr[i+1] >= '0') && (verstr[i+1] <= '9')) {
-
 
66
          if (dotcounter > 6) return(-1);
-
 
67
          digits[dotcounter++] = &verstrcopy[i + 1];
-
 
68
          verstrcopy[i] = 0;
-
 
69
        }
-
 
70
        break;
-
 
71
      case '1':
-
 
72
      case '2':
-
 
73
      case '3':
-
 
74
      case '4':
-
 
75
      case '5':
-
 
76
      case '6':
-
 
77
      case '7':
-
 
78
      case '8':
-
 
79
      case '9':
-
 
80
        firstcharaftersep = 0;
-
 
81
        break;
-
 
82
      default: /* do not allow any character different than 0..9 or '.' */
-
 
83
        return(-1);
-
 
84
        break;
-
 
85
    }
-
 
86
  }
-
 
87
  verstrcopy[i] = 0;
-
 
88
  /* now that we know the input is sane, let's process it */
-
 
89
  for (i = 0; i < dotcounter; i++) {
-
 
90
    int tmpint;
-
 
91
    tmpint = atoi(digits[i]);
-
 
92
    if ((tmpint < 0) || (tmpint > 32000)) return(-1);
-
 
93
    arr[i] = tmpint;
-
 
94
  }
-
 
95
  return(0);
-
 
96
}
-
 
97
 
-
 
98
 
-
 
99
/* compares version strings v1 and v2. Returns 1 if v2 is newer than v1, 0 otherwise, and -1 if comparison is unable to tell */
-
 
100
int isversionnewer(char *v1, char *v2) {
-
 
101
  int x1[8], x2[8], i;
-
 
102
  if ((v1 == NULL) || (v2 == NULL)) return(-1); /* if input is invalid (NULL), don't continue */
-
 
103
  if (strcasecmp(v1, v2) == 0) return(0);  /* if both versions are the same, don't continue */
-
 
104
  /* check versions of the decimal format 1.23... */
-
 
105
  if ((versiontointarr(v1, x1) != 0) || (versiontointarr(v2, x2) != 0)) return(-1);
-
 
106
  for (i = 0; i < 8; i++) {
-
 
107
    if (x2[i] > x1[i]) return(1);
-
 
108
    if (x2[i] < x1[i]) return(0);
-
 
109
  }
-
 
110
  return(0);
-
 
111
}
-
 
112
 
-
 
113
 
-
 
114
/* change all / to \ in a string */
20
/* change all / to \ in a string */
115
void slash2backslash(char *str) {
21
void slash2backslash(char *str) {
116
  int x;
22
  int x;
117
  for (x = 0; str[x] != 0; x++) {
23
  for (x = 0; str[x] != 0; x++) {
118
    if (str[x] == '/') str[x] = '\\';
24
    if (str[x] == '/') str[x] = '\\';
119
  }
25
  }
120
}
26
}
121
 
27
 
122
 
28
 
123
void removeDoubleBackslashes(char *str) {
29
void removeDoubleBackslashes(char *str) {
124
  char *curpos;
30
  char *curpos;
125
  int x;
31
  int x;
126
  for (;;) {
32
  for (;;) {
127
    curpos = strstr(str, "\\\\");
33
    curpos = strstr(str, "\\\\");
128
    if (curpos == NULL) return; /* job done */
34
    if (curpos == NULL) return; /* job done */
129
    for (x = 1; curpos[x] != 0; x++) {
35
    for (x = 1; curpos[x] != 0; x++) {
130
      curpos[x - 1] = curpos[x];
36
      curpos[x - 1] = curpos[x];
131
    }
37
    }
132
    curpos[x - 1] = 0;
38
    curpos[x - 1] = 0;
133
  }
39
  }
134
}
40
}
135
 
41
 
136
 
42
 
137
/* converts a string to all lowercase */
43
/* converts a string to all lowercase */
138
void strtolower(char *mystring) {
44
void strtolower(char *mystring) {
139
  int x;
45
  int x;
140
  for (x = 0; mystring[x] != 0; x++) mystring[x] = tolower(mystring[x]);
46
  for (x = 0; mystring[x] != 0; x++) mystring[x] = tolower(mystring[x]);
141
}
47
}
142
 
48
 
143
 
49
 
144
/* Find the first occurrence of find in s, ignore case. */
50
/* Find the first occurrence of find in s, ignore case. */
145
char *fdnpkg_strcasestr(const char *s, const char *find) {
51
char *fdnpkg_strcasestr(const char *s, const char *find) {
146
  char c, sc;
52
  char c, sc;
147
  size_t len;
53
  size_t len;
148
  if ((c = *find++) != 0) {
54
  if ((c = *find++) != 0) {
149
    c = tolower((unsigned char)c);
55
    c = tolower((unsigned char)c);
150
    len = strlen(find);
56
    len = strlen(find);
151
    do {
57
    do {
152
      do {
58
      do {
153
        if ((sc = *s++) == 0) return(NULL);
59
        if ((sc = *s++) == 0) return(NULL);
154
      } while ((char)tolower((unsigned char)sc) != c);
60
      } while ((char)tolower((unsigned char)sc) != c);
155
    } while (strncasecmp(s, find, len) != 0);
61
    } while (strncasecmp(s, find, len) != 0);
156
    s--;
62
    s--;
157
  }
63
  }
158
  return((char *)s);
64
  return((char *)s);
159
}
65
}
160
 
66
 
161
 
67
 
162
/* Creates directories recursively */
68
/* Creates directories recursively */
163
void mkpath(char *dirs) {
69
void mkpath(char *dirs) {
164
  int x;
70
  int x;
165
  char savechar;
71
  char savechar;
166
  for (x = 0; dirs[x] != 0; x++) {
72
  for (x = 0; dirs[x] != 0; x++) {
167
    if (((dirs[x] == '/') || (dirs[x] == '\\')) && (x > 0)) {
73
    if (((dirs[x] == '/') || (dirs[x] == '\\')) && (x > 0)) {
168
      if (dirs[x - 1] != ':') { /* avoid d:\ stuff */
74
      if (dirs[x - 1] != ':') { /* avoid d:\ stuff */
169
        savechar = dirs[x];
75
        savechar = dirs[x];
170
        dirs[x] = 0;
76
        dirs[x] = 0;
171
        /* make the dir */
77
        /* make the dir */
172
        mkdir(dirs);
78
        mkdir(dirs);
173
        dirs[x] = savechar;
79
        dirs[x] = savechar;
174
      }
80
      }
175
    }
81
    }
176
  }
82
  }
177
}
83
}
178
 
84
 
179
 
85
 
180
/* returns a pointer to the start of the filename, out of a path\to\file string, and
86
/* returns a pointer to the start of the filename, out of a path\to\file string, and
181
   fills respath with the local folder where the file should be placed. */
87
   fills respath with the local folder where the file should be placed. */
182
char *computelocalpath(char *longfilename, char *respath, const char *dosdir, const struct customdirs *dirlist) {
88
char *computelocalpath(char *longfilename, char *respath, const char *dosdir, const struct customdirs *dirlist) {
183
  int x, lastsep = 0, firstsep = -1;
89
  int x, lastsep = 0, firstsep = -1;
184
  char savedchar;
90
  char savedchar;
185
  char *shortfilename, *pathstart;
91
  char *shortfilename, *pathstart;
186
  pathstart = longfilename;
92
  pathstart = longfilename;
187
  for (x = 0; longfilename[x] != 0; x++) {
93
  for (x = 0; longfilename[x] != 0; x++) {
188
    if ((longfilename[x] == '/') || (longfilename[x] == '\\')) {
94
    if ((longfilename[x] == '/') || (longfilename[x] == '\\')) {
189
      lastsep = x;
95
      lastsep = x;
190
      if (firstsep < 0) firstsep = x;
96
      if (firstsep < 0) firstsep = x;
191
    }
97
    }
192
  }
98
  }
193
  shortfilename = &longfilename[lastsep + 1];
99
  shortfilename = &longfilename[lastsep + 1];
194
  /* look for possible custom path */
100
  /* look for possible custom path */
195
  if (firstsep > 0) {
101
  if (firstsep > 0) {
196
    savedchar = longfilename[firstsep];
102
    savedchar = longfilename[firstsep];
197
    longfilename[firstsep] = 0;
103
    longfilename[firstsep] = 0;
198
    for (; dirlist != NULL; dirlist = dirlist->next) {
104
    for (; dirlist != NULL; dirlist = dirlist->next) {
199
      if (fdnpkg_strcasestr(longfilename, dirlist->name) == longfilename) { /* found! */
105
      if (fdnpkg_strcasestr(longfilename, dirlist->name) == longfilename) { /* found! */
200
        /* sprintf(respath, "%s\\%s", dirlist->location, &longfilename[firstsep + 1]); */
106
        /* sprintf(respath, "%s\\%s", dirlist->location, &longfilename[firstsep + 1]); */
201
        pathstart = &longfilename[firstsep + 1];
107
        pathstart = &longfilename[firstsep + 1];
202
        dosdir = dirlist->location;
108
        dosdir = dirlist->location;
203
        break;
109
        break;
204
      }
110
      }
205
    }
111
    }
206
    longfilename[firstsep] = savedchar; /* restore longfilename as it was */
112
    longfilename[firstsep] = savedchar; /* restore longfilename as it was */
207
  }
113
  }
208
  /* apply the default (DOSDIR) path */
114
  /* apply the default (DOSDIR) path */
209
  savedchar = longfilename[lastsep + 1];
115
  savedchar = longfilename[lastsep + 1];
210
  longfilename[lastsep + 1] = 0;
116
  longfilename[lastsep + 1] = 0;
211
  sprintf(respath, "%s\\%s", dosdir, pathstart);
117
  sprintf(respath, "%s\\%s", dosdir, pathstart);
212
  slash2backslash(respath);
118
  slash2backslash(respath);
213
  removeDoubleBackslashes(respath);
119
  removeDoubleBackslashes(respath);
214
  longfilename[lastsep + 1] = savedchar;
120
  longfilename[lastsep + 1] = savedchar;
215
  return(shortfilename);
121
  return(shortfilename);
216
}
122
}
217
 
123
 
218
 
124
 
219
/* detect local paths (eg. C:\REPO). Returns 1 if the url looks like a local path, zero otherwise. */
125
/* detect local paths (eg. C:\REPO). Returns 1 if the url looks like a local path, zero otherwise. */
220
int detect_localpath(char *url) {
126
int detect_localpath(char *url) {
221
  if (url[0] != 0) {
127
  if (url[0] != 0) {
222
    if (url[1] != 0) {
128
    if (url[1] != 0) {
223
      if ((url[1] == ':') && ((url[2] == '\\') || (url[2] == '/'))) return(1);
129
      if ((url[1] == ':') && ((url[2] == '\\') || (url[2] == '/'))) return(1);
224
    }
130
    }
225
  }
131
  }
226
  return(0);
132
  return(0);
227
}
133
}
228
 
134
 
229
 
135
 
230
/* analyzes a filename string and returns the pointer to the file's extension
136
/* analyzes a filename string and returns the pointer to the file's extension
231
 * (which can be empty) */
137
 * (which can be empty) */
232
char *getfext(char *fname) {
138
char *getfext(char *fname) {
233
  char *res = NULL;
139
  char *res = NULL;
234
  for (; *fname != 0; fname++) {
140
  for (; *fname != 0; fname++) {
235
    if (*fname == '.') res = fname + 1;
141
    if (*fname == '.') res = fname + 1;
236
  }
142
  }
237
  /* if no dot found, then point to the string's null terminator */
143
  /* if no dot found, then point to the string's null terminator */
238
  if (res == NULL) return(fname);
144
  if (res == NULL) return(fname);
239
  return(res);
145
  return(res);
240
}
146
}
241
 
147
 
242
 
148
 
243
/* reads a line from a "token = value" file, returns 0 on success
149
/* reads a line from a "token = value" file, returns 0 on success
244
 * val (if not NULL) is updated with a pointer to the "value" part
150
 * val (if not NULL) is updated with a pointer to the "value" part
245
 * delim is the delimiter char (typically ':' or '=' but can be anything) */
151
 * delim is the delimiter char (typically ':' or '=' but can be anything) */
246
int freadtokval(FILE *fd, char *line, size_t maxlen, char **val, char delim) {
152
int freadtokval(FILE *fd, char *line, size_t maxlen, char **val, char delim) {
247
  int bytebuff, linelen = 0;
153
  int bytebuff, linelen = 0;
248
  if (val != NULL) *val = NULL;
154
  if (val != NULL) *val = NULL;
249
  for (;;) {
155
  for (;;) {
250
    bytebuff = fgetc(fd);
156
    bytebuff = fgetc(fd);
251
    if (bytebuff == EOF) {
157
    if (bytebuff == EOF) {
252
      if (linelen == 0) return(-1);
158
      if (linelen == 0) return(-1);
253
      break;
159
      break;
254
    }
160
    }
255
    if (bytebuff < 0) return(-1);
161
    if (bytebuff < 0) return(-1);
256
    if ((*val == NULL) && (bytebuff == delim)) {
162
    if ((*val == NULL) && (bytebuff == delim)) {
257
      line[linelen++] = 0;
163
      line[linelen++] = 0;
258
      *val = line + linelen;
164
      *val = line + linelen;
259
      continue;
165
      continue;
260
    }
166
    }
261
    if (bytebuff == '\r') continue; /* ignore CR */
167
    if (bytebuff == '\r') continue; /* ignore CR */
262
    if (bytebuff == '\n') break;
168
    if (bytebuff == '\n') break;
263
    if (linelen < maxlen - 1) line[linelen++] = bytebuff;
169
    if (linelen < maxlen - 1) line[linelen++] = bytebuff;
264
  }
170
  }
265
  /* terminate line and trim token and value (if any) */
171
  /* terminate line and trim token and value (if any) */
266
  line[linelen] = 0;
172
  line[linelen] = 0;
267
  trim(line);
173
  trim(line);
268
  if ((val != NULL) && (*val != NULL)) trim(*val);
174
  if ((val != NULL) && (*val != NULL)) trim(*val);
269
  return(0);
175
  return(0);
270
}
176
}
271
 
177