Subversion Repositories SvarDOS

Rev

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

Rev Author Line No. Line
219 mateuszvis 1
/*
994 mateusz.vi 2
 * This file is part of pkg (SvarDOS package manager)
1678 mateusz.vi 3
 * Copyright (C) 2012-2024 Mateusz Viste
219 mateuszvis 4
 *
5
 * It contains a few helper function...
6
 */
7
 
8
 
9
#include <ctype.h>    /* tolower() */
240 mateuszvis 10
#include <direct.h>   /* provides the mkdir() prototype */
219 mateuszvis 11
#include <string.h>   /* */
2232 bernd.boec 12
#include <strings.h>  /* strcasecmp() */
219 mateuszvis 13
#include <stdio.h>    /* sprintf() */
14
#include <stdlib.h>   /* atoi() */
15
#include <sys/stat.h> /* mkdir() */
16
 
256 mateuszvis 17
#include "trim.h"
219 mateuszvis 18
#include "helpers.h"
19
 
20
 
1964 mateusz.vi 21
/* converts a CRC32 into a (hex) string */
22
char *crc32tostring(char *s, unsigned long val) {
23
  signed char i;
24
  static char h[] = "0123456789ABCDEF";
25
  for (i = 7; i >= 0; i--) {
26
    s[i] = h[val & 15];
27
    val >>= 4;
28
  }
29
  s[8] = 0;
30
  return(s);
31
}
1893 mateusz.vi 32
 
1964 mateusz.vi 33
 
1893 mateusz.vi 34
/* outputs a NUL-terminated string to stdout */
35
void output(const char *s) {
36
  _asm {
37
    push ds
38
    push es
39
    /* get length of s into CX */
40
    mov ax, 0x4000 /* ah=DOS "write to file" and AL=0 for NUL matching */
41
    lds dx, s      /* set DS:DX to string (required for later) */
42
    push ds
43
    pop es         /* make sure es=ds (scasb uses es) */
44
    mov di, dx     /* set di to string (for NULL matching) */
45
    mov cx, 0xffff /* preset cx to 65535 (-1) */
46
    cld            /* clear DF so scasb increments DI */
47
    repne scasb    /* cmp al, es:[di], inc di, dec cx until match found */
48
    /* CX contains (65535 - strlen(s)) now */
49
    not cx         /* reverse all bits so I get (strlen(s) + 1) */
50
    dec cx         /* this is CX length */
51
    jz WRITEDONE   /* do nothing for empty strings */
52
 
53
    /* output by writing to stdout */
54
    /* mov ah, 0x40 */  /* DOS 2+ -- write to file via handle */
55
    xor bh, bh
56
    mov bl, 1 /* set handle (1=stdout 2=stderr) */
57
    /* mov cx, xxx */ /* write CX bytes */
58
    /* mov dx, s   */ /* DS:DX is the source of bytes to "write" */
59
    int 0x21
60
    WRITEDONE:
61
    pop es
62
    pop ds
63
  }
64
}
65
 
66
 
1959 mateusz.vi 67
void outputnl(const char *s) {
68
  output(s);
69
  output("\r\n");
70
}
71
 
72
 
219 mateuszvis 73
/* change all / to \ in a string */
74
void slash2backslash(char *str) {
75
  int x;
76
  for (x = 0; str[x] != 0; x++) {
77
    if (str[x] == '/') str[x] = '\\';
78
  }
79
}
80
 
81
 
1678 mateusz.vi 82
/* trim CRC from a filename and returns a pointer to the CRC part.
83
 * this is used to parse filename lines from LSM files */
84
char *trimfnamecrc(char *fname) {
85
  while (*fname) {
86
    if (*fname == '?') {
87
      *fname = 0;
88
      return(fname + 1);
89
    }
90
    fname++;
91
  }
1959 mateusz.vi 92
  return(NULL);
1678 mateusz.vi 93
}
94
 
95
 
219 mateuszvis 96
void removeDoubleBackslashes(char *str) {
97
  char *curpos;
98
  int x;
99
  for (;;) {
251 mateuszvis 100
    curpos = strstr(str, "\\\\");
219 mateuszvis 101
    if (curpos == NULL) return; /* job done */
102
    for (x = 1; curpos[x] != 0; x++) {
103
      curpos[x - 1] = curpos[x];
104
    }
105
    curpos[x - 1] = 0;
106
  }
107
}
108
 
109
 
110
/* Find the first occurrence of find in s, ignore case. */
111
char *fdnpkg_strcasestr(const char *s, const char *find) {
112
  char c, sc;
113
  size_t len;
114
  if ((c = *find++) != 0) {
115
    c = tolower((unsigned char)c);
116
    len = strlen(find);
117
    do {
118
      do {
119
        if ((sc = *s++) == 0) return(NULL);
120
      } while ((char)tolower((unsigned char)sc) != c);
121
    } while (strncasecmp(s, find, len) != 0);
122
    s--;
123
  }
124
  return((char *)s);
125
}
126
 
127
 
128
/* Creates directories recursively */
129
void mkpath(char *dirs) {
130
  int x;
131
  char savechar;
132
  for (x = 0; dirs[x] != 0; x++) {
133
    if (((dirs[x] == '/') || (dirs[x] == '\\')) && (x > 0)) {
134
      if (dirs[x - 1] != ':') { /* avoid d:\ stuff */
135
        savechar = dirs[x];
136
        dirs[x] = 0;
137
        /* make the dir */
240 mateuszvis 138
        mkdir(dirs);
219 mateuszvis 139
        dirs[x] = savechar;
140
      }
141
    }
142
  }
143
}
144
 
145
 
146
/* returns a pointer to the start of the filename, out of a path\to\file string, and
147
   fills respath with the local folder where the file should be placed. */
1892 mateusz.vi 148
char *computelocalpath(char *longfilename, char *respath, const char *dosdir, const struct customdirs *dirlist, char bootdrive) {
219 mateuszvis 149
  int x, lastsep = 0, firstsep = -1;
150
  char savedchar;
151
  char *shortfilename, *pathstart;
152
  pathstart = longfilename;
153
  for (x = 0; longfilename[x] != 0; x++) {
154
    if ((longfilename[x] == '/') || (longfilename[x] == '\\')) {
155
      lastsep = x;
156
      if (firstsep < 0) firstsep = x;
157
    }
158
  }
1878 mateusz.vi 159
  /* if it's a file without any directory, then it goes to BOOTDRIVE:\ (COMMAND.COM, KERNEL.SYS...) */
994 mateusz.vi 160
  if (firstsep < 0) {
1892 mateusz.vi 161
    sprintf(respath, "%c:\\", bootdrive);
994 mateusz.vi 162
    return(longfilename);
163
  }
164
  /* */
219 mateuszvis 165
  shortfilename = &longfilename[lastsep + 1];
166
  /* look for possible custom path */
167
  if (firstsep > 0) {
168
    savedchar = longfilename[firstsep];
169
    longfilename[firstsep] = 0;
170
    for (; dirlist != NULL; dirlist = dirlist->next) {
171
      if (fdnpkg_strcasestr(longfilename, dirlist->name) == longfilename) { /* found! */
172
        /* sprintf(respath, "%s\\%s", dirlist->location, &longfilename[firstsep + 1]); */
173
        pathstart = &longfilename[firstsep + 1];
174
        dosdir = dirlist->location;
175
        break;
176
      }
177
    }
178
    longfilename[firstsep] = savedchar; /* restore longfilename as it was */
179
  }
180
  /* apply the default (DOSDIR) path */
181
  savedchar = longfilename[lastsep + 1];
182
  longfilename[lastsep + 1] = 0;
183
  sprintf(respath, "%s\\%s", dosdir, pathstart);
184
  slash2backslash(respath);
185
  removeDoubleBackslashes(respath);
186
  longfilename[lastsep + 1] = savedchar;
187
  return(shortfilename);
188
}
189
 
190
 
191
/* analyzes a filename string and returns the pointer to the file's extension
192
 * (which can be empty) */
193
char *getfext(char *fname) {
194
  char *res = NULL;
195
  for (; *fname != 0; fname++) {
196
    if (*fname == '.') res = fname + 1;
197
  }
198
  /* if no dot found, then point to the string's null terminator */
199
  if (res == NULL) return(fname);
200
  return(res);
201
}
248 mateuszvis 202
 
203
 
204
/* reads a line from a "token = value" file, returns 0 on success
205
 * val (if not NULL) is updated with a pointer to the "value" part
206
 * delim is the delimiter char (typically ':' or '=' but can be anything) */
207
int freadtokval(FILE *fd, char *line, size_t maxlen, char **val, char delim) {
208
  int bytebuff, linelen = 0;
209
  if (val != NULL) *val = NULL;
210
  for (;;) {
211
    bytebuff = fgetc(fd);
212
    if (bytebuff == EOF) {
213
      if (linelen == 0) return(-1);
214
      break;
215
    }
216
    if (bytebuff < 0) return(-1);
217
    if ((*val == NULL) && (bytebuff == delim)) {
218
      line[linelen++] = 0;
219
      *val = line + linelen;
220
      continue;
221
    }
222
    if (bytebuff == '\r') continue; /* ignore CR */
223
    if (bytebuff == '\n') break;
224
    if (linelen < maxlen - 1) line[linelen++] = bytebuff;
225
  }
226
  /* terminate line and trim token and value (if any) */
227
  line[linelen] = 0;
228
  trim(line);
229
  if ((val != NULL) && (*val != NULL)) trim(*val);
230
  return(0);
231
}