Subversion Repositories SvarDOS

Rev

Rev 219 | Rev 231 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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