Subversion Repositories SvarDOS

Rev

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

Rev 184 Rev 185
1
/*
1
/*
2
  FDNPKG idx builder
2
  SvarDOS repo index builder
3
  Copyright (C) Mateusz Viste 2012, 2013, 2014, 2015, 2016, 2017
3
  Copyright (C) Mateusz Viste 2012-2021
4

4

5
  buildidx computes idx files for FDNPKG-compatible repositories.
5
  buildidx computes an index tsv file for the SvarDOS repository.
6
  it must be executed pointing to a directory that stores FreeDOS
6
  it must be executed pointing to a directory that stores packages (zip)
7
  packages (zip) files. buildidx will generate the index file and
7
  files. buildidx will generate the index file and save it into the package
8
  save it into the package repository.
8
  repository.
9

9

-
 
10
  13 jan 2021: removed the identification line, changed CRC32 to bsum, not creating the listing.txt file and stopped compressing index
10
  23 apr 2017: uncompressed index is no longer created, added CRC32 of zib (bin only) files, if present
11
  23 apr 2017: uncompressed index is no longer created, added CRC32 of zib (bin only) files, if present
11
  28 aug 2016: listing.txt is always written inside the repo dir (instead of inside current dir)
12
  28 aug 2016: listing.txt is always written inside the repo dir (instead of inside current dir)
12
  27 aug 2016: accepting full paths to repos (starting with /...)
13
  27 aug 2016: accepting full paths to repos (starting with /...)
13
  07 dec 2013: rewritten buildidx in ANSI C89
14
  07 dec 2013: rewritten buildidx in ANSI C89
14
  19 aug 2013: add a compressed version of the index file to repos (index.gz)
15
  19 aug 2013: add a compressed version of the index file to repos (index.gz)
15
  22 jul 2013: creating a listing.txt file with list of packages
16
  22 jul 2013: creating a listing.txt file with list of packages
16
  18 jul 2013: writing the number of packaged into the first line of the lst file
17
  18 jul 2013: writing the number of packaged into the first line of the lst file
17
  11 jul 2013: added a switch to 7za to make it case insensitive when extracting lsm files
18
  11 jul 2013: added a switch to 7za to make it case insensitive when extracting lsm files
18
  10 jul 2013: changed unzip calls to 7za (to handle cases when appinfo is compressed with lzma)
19
  10 jul 2013: changed unzip calls to 7za (to handle cases when appinfo is compressed with lzma)
19
  04 feb 2013: added CRC32 support
20
  04 feb 2013: added CRC32 support
20
  22 sep 2012: forked 1st version from FDUPDATE builder
21
  22 sep 2012: forked 1st version from FDUPDATE builder
21
*/
22
*/
22
 
23
 
23
#include <errno.h>
24
#include <errno.h>
24
#include <stdio.h>   /* fopen, fclose... */
25
#include <stdio.h>   /* fopen, fclose... */
-
 
26
#include <stdint.h>
25
#include <stdlib.h>  /* system() */
27
#include <stdlib.h>  /* system() */
26
#include <string.h>  /* strcasecmp() */
28
#include <string.h>  /* strcasecmp() */
27
#include <time.h>    /* time(), ctime() */
29
#include <time.h>    /* time(), ctime() */
28
#include <unistd.h>  /* read() */
30
#include <unistd.h>  /* read() */
29
#include <dirent.h>
31
#include <dirent.h>
30
#include <sys/types.h>
32
#include <sys/types.h>
31
 
33
 
32
#define pVer "2017-04-23"
34
#define pVer "2021-01-13"
33
 
35
 
34
 
36
 
35
#include "crc32lib.c"
-
 
36
 
-
 
37
 
-
 
38
/* computes the CRC32 of file and returns it. returns 0 on error. */
37
/* computes the BSD sum of a file and returns it. returns 0 on error. */
39
static unsigned long file2crc(char *filename) {
38
static uint16_t file2bsum(char *filename) {
40
  unsigned long result;
39
  uint16_t result = 0;
41
  unsigned char buff[16 * 1024];
40
  unsigned char buff[1024 * 1024];
42
  int buffread;
41
  size_t i, buffread;
43
  FILE *fd;
42
  FILE *fd;
44
  fd = fopen(filename, "rb");
43
  fd = fopen(filename, "rb");
45
  if (fd == NULL) return(0);
44
  if (fd == NULL) return(0);
46
  result = crc32_init();
-
 
47
  while ((buffread = fread(buff, 1, sizeof(buff), fd)) > 0) {
45
  while ((buffread = fread(buff, 1, sizeof(buff), fd)) > 0) {
-
 
46
    for (i = 0; i < buffread; i++) {
-
 
47
      /* rotr */
48
    if (buffread > 0) crc32_feed(&result, buff, buffread);
48
      result = (result >> 1) | (result << 15);
-
 
49
      /* */
-
 
50
      result += buff[i];
-
 
51
    }
49
  }
52
  }
50
  crc32_finish(&result);
-
 
51
  fclose(fd);
53
  fclose(fd);
52
  if (buffread < 0) puts("read() error!");
-
 
53
  return(result);
54
  return(result);
54
}
55
}
55
 
56
 
56
 
57
 
57
static void trim(char *str) {
58
static void trim(char *str) {
58
  int x, y, firstchar = -1, lastchar = -1;
59
  int x, y, firstchar = -1, lastchar = -1;
59
  for (x = 0; str[x] != 0; x++) {
60
  for (x = 0; str[x] != 0; x++) {
60
    switch (str[x]) {
61
    switch (str[x]) {
61
      case ' ':
62
      case ' ':
62
      case '\t':
63
      case '\t':
63
      case '\n':
64
      case '\n':
64
      case '\r':
65
      case '\r':
65
        break;
66
        break;
66
      default:
67
      default:
67
        if (firstchar < 0) firstchar = x;
68
        if (firstchar < 0) firstchar = x;
68
        lastchar = x;
69
        lastchar = x;
69
        break;
70
        break;
70
    }
71
    }
71
  }
72
  }
72
  str[lastchar + 1] = 0; /* right trim */
73
  str[lastchar + 1] = 0; /* right trim */
73
  if (firstchar > 0) { /* left trim (shift to the left ) */
74
  if (firstchar > 0) { /* left trim (shift to the left ) */
74
    y = 0;
75
    y = 0;
75
    for (x = firstchar; str[x] != 0; x++) str[y++] = str[x];
76
    for (x = firstchar; str[x] != 0; x++) str[y++] = str[x];
76
    str[y] = 0;
77
    str[y] = 0;
77
  }
78
  }
78
}
79
}
79
 
80
 
80
 
81
 
81
/* reads a line from a file descriptor, and writes it to *line, the *line array is filled no more than maxlen bytes. returns the number of byte read on success, or a negative value on failure (reaching EOF is considered an error condition) */
82
/* reads a line from a file descriptor, and writes it to *line, the *line array is filled no more than maxlen bytes. returns the number of byte read on success, or a negative value on failure (reaching EOF is considered an error condition) */
82
static int readline_fromfile(FILE *fd, char *line, int maxlen) {
83
static int readline_fromfile(FILE *fd, char *line, int maxlen) {
83
  int bytebuff, linelen = 0;
84
  int bytebuff, linelen = 0;
84
  for (;;) {
85
  for (;;) {
85
    bytebuff = fgetc(fd);
86
    bytebuff = fgetc(fd);
86
    if (bytebuff == EOF) {
87
    if (bytebuff == EOF) {
87
      line[linelen] = 0;
88
      line[linelen] = 0;
88
      if (linelen == 0) return(-1);
89
      if (linelen == 0) return(-1);
89
      return(linelen);
90
      return(linelen);
90
    }
91
    }
91
    if (bytebuff < 0) return(-1);
92
    if (bytebuff < 0) return(-1);
92
    if (bytebuff == '\r') continue; /* ignore CR */
93
    if (bytebuff == '\r') continue; /* ignore CR */
93
    if (bytebuff == '\n') {
94
    if (bytebuff == '\n') {
94
      line[linelen] = 0;
95
      line[linelen] = 0;
95
      return(linelen);
96
      return(linelen);
96
    }
97
    }
97
    if (linelen < maxlen) line[linelen++] = bytebuff;
98
    if (linelen < maxlen) line[linelen++] = bytebuff;
98
  }
99
  }
99
}
100
}
100
 
101
 
101
static int readlsm(char *filename, char *version, char *title, char *description) {
102
static int readlsm(char *filename, char *version, char *title, char *description) {
102
  char linebuff[1024];
103
  char linebuff[1024];
103
  char *valuestr;
104
  char *valuestr;
104
  int x;
105
  int x;
105
  FILE *fd;
106
  FILE *fd;
106
  /* reset fields to be read to empty values */
107
  /* reset fields to be read to empty values */
107
  version[0] = 0;
108
  version[0] = 0;
108
  description[0] = 0;
109
  description[0] = 0;
109
  title[0] = 0;
110
  title[0] = 0;
110
  /* open the file */
111
  /* open the file */
111
  fd = fopen(filename, "rb");
112
  fd = fopen(filename, "rb");
112
  if (fd == NULL) return(-1);
113
  if (fd == NULL) return(-1);
113
  /* check the file's header */
114
  /* check the file's header */
114
  if (readline_fromfile(fd, linebuff, 64) < 0) return(-1);
115
  if (readline_fromfile(fd, linebuff, 64) < 0) return(-1);
115
  if (strcasecmp(linebuff, "begin3") != 0) return(-1);
116
  if (strcasecmp(linebuff, "begin3") != 0) return(-1);
116
  /* read the LSM file line by line */
117
  /* read the LSM file line by line */
117
  while (readline_fromfile(fd, linebuff, 127) >= 0) {
118
  while (readline_fromfile(fd, linebuff, 127) >= 0) {
118
    for (x = 0;; x++) {
119
    for (x = 0;; x++) {
119
      if (linebuff[x] == 0) {
120
      if (linebuff[x] == 0) {
120
        x = -1;
121
        x = -1;
121
        break;
122
        break;
122
      } else if (linebuff[x] == ':') {
123
      } else if (linebuff[x] == ':') {
123
        break;
124
        break;
124
      }
125
      }
125
    }
126
    }
126
    if (x > 0) {
127
    if (x > 0) {
127
      linebuff[x] = 0;
128
      linebuff[x] = 0;
128
      valuestr = linebuff + x + 1;
129
      valuestr = linebuff + x + 1;
129
      trim(linebuff);
130
      trim(linebuff);
130
      trim(valuestr);
131
      trim(valuestr);
131
      if (strcasecmp(linebuff, "version") == 0) {
132
      if (strcasecmp(linebuff, "version") == 0) {
132
          sprintf(version, "%s", valuestr);
133
          sprintf(version, "%s", valuestr);
133
        } else if (strcasecmp(linebuff, "title") == 0) {
134
        } else if (strcasecmp(linebuff, "title") == 0) {
134
          sprintf(title, "%s", valuestr);
135
          sprintf(title, "%s", valuestr);
135
        } else if (strcasecmp(linebuff, "description") == 0) {
136
        } else if (strcasecmp(linebuff, "description") == 0) {
136
          sprintf(description, "%s", valuestr);
137
          sprintf(description, "%s", valuestr);
137
      }
138
      }
138
    }
139
    }
139
  }
140
  }
140
  fclose(fd);
141
  fclose(fd);
141
  return(0);
142
  return(0);
142
}
143
}
143
 
144
 
144
 
145
 
145
static int cmpstring(const void *p1, const void *p2) {
146
static int cmpstring(const void *p1, const void *p2) {
146
    /* The actual arguments to this function are "pointers to
147
    /* The actual arguments to this function are "pointers to
147
       pointers to char", but strcmp(3) arguments are "pointers
148
       pointers to char", but strcmp(3) arguments are "pointers
148
       to char", hence the following cast plus dereference */
149
       to char", hence the following cast plus dereference */
149
   return(strcasecmp(* (char * const *) p1, * (char * const *) p2));
150
   return(strcasecmp(* (char * const *) p1, * (char * const *) p2));
150
}
151
}
151
 
152
 
152
 
153
 
153
static char *getlastdir(char *s) {
-
 
154
  char *r = s;
-
 
155
  for (; *s != 0; s++) {
-
 
156
    if ((*s == '/') && (s[1] != 0)) r = s+1;
-
 
157
  }
-
 
158
  return(r);
-
 
159
}
-
 
160
 
-
 
161
 
-
 
162
static void GenIndexes(char *repodir) {
154
static void GenIndexes(char *repodir) {
163
  char *LsmFileList[4096];
155
  char *LsmFileList[4096];
164
  char tmpbuf[64];
156
  char tmpbuf[64];
165
  char *LsmFile, LSMpackage[64], LSMtitle[128], LSMversion[128], LSMdescription[1024];
157
  char *LsmFile, LSMpackage[64], LSMtitle[128], LSMversion[128], LSMdescription[1024];
166
  int LsmCount = 0, x;
158
  int LsmCount = 0, x;
167
  FILE *idx, *listing;
159
  FILE *idx;
168
  time_t curtime;
-
 
169
  DIR *dir;
160
  DIR *dir;
170
  struct dirent *diritem;
161
  struct dirent *diritem;
171
 
162
 
172
  dir = opendir("appinfo");
163
  dir = opendir("appinfo");
173
  if (dir == NULL) {
164
  if (dir == NULL) {
174
    printf("ERROR: Unable to open directory '%s' (%s)\n", repodir, strerror(errno));
165
    printf("ERROR: Unable to open directory '%s' (%s)\n", repodir, strerror(errno));
175
    return;
166
    return;
176
  }
167
  }
177
 
168
 
178
  /* load the content of the appinfo directory */
169
  /* load the content of the appinfo directory */
179
  while ((diritem = readdir(dir)) != NULL) {
170
  while ((diritem = readdir(dir)) != NULL) {
180
    if (strstr(diritem->d_name, ".lsm") == NULL) continue; /* skip files that do not contain '.lsm' */
171
    if (strstr(diritem->d_name, ".lsm") == NULL) continue; /* skip files that do not contain '.lsm' */
181
    LsmFileList[LsmCount] = strdup(diritem->d_name);
172
    LsmFileList[LsmCount] = strdup(diritem->d_name);
182
    /* printf("Loaded LSM file: %s\n", LsmFileList[LsmCount]); */
173
    /* printf("Loaded LSM file: %s\n", LsmFileList[LsmCount]); */
183
    LsmCount += 1;
174
    LsmCount += 1;
184
  }
175
  }
185
 
176
 
186
  closedir(dir);
177
  closedir(dir);
187
 
178
 
188
  printf("Found %d LSM files\n", LsmCount);
179
  printf("Found %d LSM files\n", LsmCount);
189
 
180
 
190
  /* sort the entries */
181
  /* sort the entries */
191
  qsort(&LsmFileList[0], LsmCount, sizeof(char *), cmpstring);
182
  qsort(&LsmFileList[0], LsmCount, sizeof(char *), cmpstring);
192
 
183
 
193
  /* Create the index file */
184
  /* Create the index file */
194
  sprintf(tmpbuf, "%s/index.lst", repodir);
185
  sprintf(tmpbuf, "%s/index.tsv", repodir);
195
  idx = fopen(tmpbuf, "wb");
186
  idx = fopen(tmpbuf, "wb");
196
  sprintf(tmpbuf, "%s/listing.txt", repodir);
-
 
197
  listing = fopen(tmpbuf, "wb");
-
 
198
 
-
 
199
  /* Write out the index header */
-
 
200
  curtime = time(NULL);
-
 
201
  fprintf(idx, "FD-REPOv1\t'%s' built at unix time %ld, lists %d packages\n", getlastdir(repodir), curtime, LsmCount);
-
 
202
  fprintf(listing, "\n");
-
 
203
  fprintf(listing, "*** Repository '%s' - build time: %s\n", getlastdir(repodir), ctime(&curtime));
-
 
204
 
187
 
205
  /* Read every LSM */
188
  /* Read every LSM */
206
  for (x = 0; x < LsmCount; x++) {
189
  for (x = 0; x < LsmCount; x++) {
207
    unsigned long crc32, crc32zib;
190
    uint16_t bsum;
208
    LsmFile = LsmFileList[x];
191
    LsmFile = LsmFileList[x];
209
    sprintf(LSMpackage, "%s", LsmFile);
192
    sprintf(LSMpackage, "%s", LsmFile);
210
    LSMpackage[strlen(LSMpackage) - 4] = 0;
193
    LSMpackage[strlen(LSMpackage) - 4] = 0;
211
 
194
 
212
    /* compute the CRC of the zip package, and its zib version, if present */
195
    /* compute the BSD sum of the zip package */
213
    sprintf(tmpbuf, "%s/%s.zip", repodir, LSMpackage);
196
    sprintf(tmpbuf, "%s/%s.zip", repodir, LSMpackage);
214
    crc32 = file2crc(tmpbuf);
197
    bsum = file2bsum(tmpbuf);
215
    sprintf(tmpbuf, "%s/%s.zib", repodir, LSMpackage);
-
 
216
    crc32zib = file2crc(tmpbuf);
-
 
217
 
198
 
218
    if (crc32zib != 0) {
-
 
219
      printf("Processing %s... CRC %08lX (zib: %08lX)\n", LsmFile, crc32, crc32zib);
-
 
220
    } else {
-
 
221
      printf("Processing %s... CRC %08lX\n", LsmFile, crc32);
199
    printf("Processing %s... BSUM %04X\n", LsmFile, bsum);
222
    }
-
 
223
 
200
 
224
    sprintf(tmpbuf, "appinfo/%s", LsmFile);
201
    sprintf(tmpbuf, "appinfo/%s", LsmFile);
225
    readlsm(tmpbuf, LSMversion, LSMtitle, LSMdescription);
202
    readlsm(tmpbuf, LSMversion, LSMtitle, LSMdescription);
226
 
203
 
227
    if (strlen(LSMpackage) > 8) printf("Warning: %s.zip is not in 8.3 format!\n", LSMpackage);
204
    if (strlen(LSMpackage) > 8) printf("Warning: %s.zip is not in 8.3 format!\n", LSMpackage);
228
    if (LSMtitle[0] == 0) printf("Warning: no LSM title for %s.zip\n", LSMpackage);
205
    if (LSMtitle[0] == 0) printf("Warning: no LSM title for %s.zip\n", LSMpackage);
229
    if (LSMversion[0] == 0) printf("Warning: no LSM version for %s.zip!\n", LSMpackage);
206
    if (LSMversion[0] == 0) printf("Warning: no LSM version for %s.zip!\n", LSMpackage);
230
    if (LSMdescription[0] == 0) printf("Warning: no LSM description for %s.zip!\n", LSMpackage);
207
    if (LSMdescription[0] == 0) printf("Warning: no LSM description for %s.zip!\n", LSMpackage);
231
    if (crc32zib != 0) {
-
 
232
      fprintf(idx, "%s\t%s\t%s\t%08lX\t%08lX\n", LSMpackage, LSMversion, LSMdescription, crc32, crc32zib);
-
 
233
    } else {
-
 
234
      fprintf(idx, "%s\t%s\t%s\t%08lX\t\n", LSMpackage, LSMversion, LSMdescription, crc32);
208
    fprintf(idx, "%s\t%s\t%s\t%u\n", LSMpackage, LSMversion, LSMdescription, bsum);
235
    }
-
 
236
    fprintf(listing, "%s %s - %s\n", LSMpackage, LSMversion, LSMdescription);
-
 
237
  }
209
  }
238
  fprintf(listing, "\n");
-
 
239
  fclose(idx);
210
  fclose(idx);
240
  fclose(listing);
-
 
241
  /* create the compressed version of the index file using gzip */
-
 
242
  sprintf(tmpbuf, "gzip -9 < %s/index.lst > %s/index.gz", repodir, repodir);
-
 
243
  system(tmpbuf);
-
 
244
  /* remove the uncompressed version */
-
 
245
  sprintf(tmpbuf, "%s/index.lst", repodir);
-
 
246
  unlink(tmpbuf);
-
 
247
  printf("%d packages found.\n", LsmCount);
211
  printf("%d packages found.\n", LsmCount);
248
}
212
}
249
 
213
 
250
 
214
 
251
 
215
 
252
int main(int argc, char **argv) {
216
int main(int argc, char **argv) {
253
  char *repodir;
217
  char *repodir;
254
  char cmdbuff[1024];
218
  char cmdbuff[1024];
255
 
219
 
256
  puts("FDNPKG server repository generator version " pVer);
220
  puts("FDNPKG server repository generator version " pVer);
257
 
221
 
258
  if (argc != 2) {
222
  if (argc != 2) {
259
    puts("Usage: buildidx repodir");
223
    puts("Usage: buildidx repodir");
260
    return(1);
224
    return(1);
261
  }
225
  }
262
 
226
 
263
  if ((argv[1][0] == '?') || (argv[1][0] == '-') || (argv[1][0]) == 0) {
227
  if ((argv[1][0] == '?') || (argv[1][0] == '-') || (argv[1][0]) == 0) {
264
    puts("Usage: buildidx repodir");
228
    puts("Usage: buildidx repodir");
265
    return(1);
229
    return(1);
266
  }
230
  }
267
 
231
 
268
  repodir = argv[1];
232
  repodir = argv[1];
269
 
233
 
270
  printf("Will build index for %s directory.\n", repodir);
234
  printf("Will build index for %s directory.\n", repodir);
271
  puts("Recreating the appinfo directory...");
235
  puts("Recreating the appinfo directory...");
272
 
236
 
273
  system("rm -rf appinfo");
237
  system("rm -rf appinfo");
274
  system("mkdir appinfo");
238
  system("mkdir appinfo");
275
 
239
 
276
  puts("Populating appinfo with LSM files from archives...");
240
  puts("Populating appinfo with LSM files from archives...");
277
  sprintf(cmdbuff, "unzip -C -j -L -o '%s/*.zip' 'appinfo/*.lsm' -d appinfo", repodir);
241
  sprintf(cmdbuff, "unzip -C -j -L -o '%s/*.zip' 'appinfo/*.lsm' -d appinfo", repodir);
278
  system(cmdbuff);
242
  system(cmdbuff);
279
 
243
 
280
  puts("Generating the index file...");
244
  puts("Generating the index file...");
281
  GenIndexes(repodir);
245
  GenIndexes(repodir);
282
 
246
 
283
  system("rm -rf appinfo");
247
  system("rm -rf appinfo");
284
  return(0);
248
  return(0);
285
}
249
}
286
 
250