Subversion Repositories SvarDOS

Rev

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

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