Subversion Repositories SvarDOS

Rev

Rev 1800 | Rev 1891 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1800 Rev 1880
Line 94... Line 94...
94
}
94
}
95
 
95
 
96
 
96
 
97
/* prepare a package for installation. this is mandatory before installing it!
97
/* prepare a package for installation. this is mandatory before installing it!
98
 * returns a pointer to the zip file's index on success, NULL on failure.
98
 * returns a pointer to the zip file's index on success, NULL on failure.
-
 
99
 * pkgname must be at least 9 bytes long and is filled with the package name.
99
 * the **zipfd pointer is updated with file descriptor of the open (to be
100
 * the **zipfd pointer is updated with file descriptor of the open (to be
100
 * installed) zip file.
101
 * installed) zip file.
101
 * the returned ziplist is guaranteed to have the APPINFO file as first node
102
 * the returned ziplist is guaranteed to have the APPINFO file as first node
102
 * the ziplist is also guaranteed not to contain any directory entries */
103
 * the ziplist is also guaranteed not to contain any directory entries */
103
struct ziplist *pkginstall_preparepackage(const char *pkgname, const char *zipfile, int flags, FILE **zipfd, const char *dosdir, const struct customdirs *dirlist) {
104
struct ziplist *pkginstall_preparepackage(char *pkgname, const char *zipfile, int flags, FILE **zipfd, const char *dosdir, const struct customdirs *dirlist) {
104
  char fname[256];
105
  char fname[256];
105
  char appinfofile[32];
-
 
106
  struct ziplist *appinfoptr;
106
  struct ziplist *appinfoptr = NULL;
107
  char *shortfile;
107
  char *shortfile;
108
  struct ziplist *ziplinkedlist = NULL, *curzipnode, *prevzipnode;
108
  struct ziplist *ziplinkedlist = NULL, *curzipnode, *prevzipnode;
109
  struct flist_t *flist = NULL;
109
  struct flist_t *flist = NULL;
110
 
110
 
111
  sprintf(appinfofile, "appinfo\\%s.lsm", pkgname); /* Prepare the appinfo/xxxx.lsm filename string for later use */
-
 
112
 
-
 
113
  /* check if not already installed, if already here, print a message "you might want to use update instead"
-
 
114
   * of course this must not be done if we are in the process of upgrading said package */
-
 
115
  if (((flags & PKGINST_UPDATE) == 0) && (validate_package_not_installed(pkgname, dosdir) != 0)) {
-
 
116
    return(NULL);
-
 
117
  }
-
 
118
 
-
 
119
  /* copy zip filename into fname */
111
  /* copy zip filename into fname */
120
  strcpy(fname, zipfile);
112
  strcpy(fname, zipfile);
121
 
113
 
122
  /* append an .SVP extension if not present */
114
  /* append an .SVP extension if not present */
123
  {
115
  {
Line 129... Line 121...
129
  if (!fileexists(fname)) {
121
  if (!fileexists(fname)) {
130
    puts(svarlang_str(10, 1)); /* ERROR: File not found */
122
    puts(svarlang_str(10, 1)); /* ERROR: File not found */
131
    goto RAII;
123
    goto RAII;
132
  }
124
  }
133
 
125
 
134
  /* now let's check the content of the zip file */
126
  /* open the SVP archive and get the list of files */
135
 
-
 
136
  *zipfd = fopen(fname, "rb");
127
  *zipfd = fopen(fname, "rb");
137
  if (*zipfd == NULL) {
128
  if (*zipfd == NULL) {
138
    puts(svarlang_str(3, 8)); /* "ERROR: Invalid zip archive! Package not installed." */
129
    puts(svarlang_str(3, 8)); /* "ERROR: Invalid zip archive! Package not installed." */
139
    goto RAII;
130
    goto RAII_ERR;
140
  }
131
  }
141
  ziplinkedlist = zip_listfiles(*zipfd);
132
  ziplinkedlist = zip_listfiles(*zipfd);
142
  if (ziplinkedlist == NULL) {
133
  if (ziplinkedlist == NULL) {
143
    puts(svarlang_str(3, 8)); /* "ERROR: Invalid zip archive! Package not installed." */
134
    puts(svarlang_str(3, 8)); /* "ERROR: Invalid zip archive! Package not installed." */
144
    goto RAII;
135
    goto RAII_ERR;
145
  }
-
 
146
  /* if updating, load the list of files belonging to the current package */
-
 
147
  if ((flags & PKGINST_UPDATE) != 0) {
-
 
148
    flist = pkg_loadflist(pkgname, dosdir);
-
 
149
  }
136
  }
150
 
137
 
151
  /* Verify that there's no collision with existing local files, look for the appinfo presence */
138
  /* process the entire ziplist and sanitize it + locate the appinfo file so
152
  appinfoptr = NULL;
139
   * I know the package name */
153
  prevzipnode = NULL;
140
  prevzipnode = NULL;
-
 
141
  curzipnode = ziplinkedlist;
-
 
142
  while (curzipnode != NULL) {
154
 
143
 
155
  for (curzipnode = ziplinkedlist; curzipnode != NULL;) {
-
 
156
    /* change all slashes to backslashes, and switch into all-lowercase */
144
    /* change all slashes to backslashes, and switch into all-lowercase */
157
    slash2backslash(curzipnode->filename);
145
    slash2backslash(curzipnode->filename);
158
    strlwr(curzipnode->filename);
146
    strlwr(curzipnode->filename);
159
    /* remove 'directory' ZIP entries to avoid false alerts about directory already existing */
-
 
160
    if ((curzipnode->flags & ZIP_FLAG_ISADIR) != 0) {
-
 
161
      curzipnode->filename[0] = 0; /* mark it "empty", will be removed in a short moment */
-
 
162
    }
-
 
163
    /* is it a "link file"? skip it - link files are no longer supported */
-
 
164
    if (strstr(curzipnode->filename, "links\\") == curzipnode->filename) {
-
 
165
      curzipnode->filename[0] = 0; /* in fact, I just mark the file as 'empty' on the filename - see later below */
-
 
166
    }
-
 
167
 
-
 
168
    /* is it the appinfo file? detach it from the list for now */
-
 
169
    if (strcmp(curzipnode->filename, appinfofile) == 0) {
-
 
170
      appinfoptr = curzipnode;
-
 
171
      curzipnode = curzipnode->nextfile;
-
 
172
      if (prevzipnode == NULL) {
-
 
173
        ziplinkedlist = curzipnode;
-
 
174
      } else {
-
 
175
        prevzipnode->nextfile = curzipnode;
-
 
176
      }
-
 
177
      continue;
-
 
178
    }
-
 
179
 
-
 
180
    if (curzipnode->filename[0] == 0) { /* ignore empty filenames (maybe it was empty originally, or has been emptied because it's a dropped source or link) */
-
 
181
      if (prevzipnode == NULL) {  /* take the item out of the list */
-
 
182
        ziplinkedlist = curzipnode->nextfile;
-
 
183
        free(curzipnode); /* free the item */
-
 
184
        curzipnode = ziplinkedlist;
-
 
185
      } else {
-
 
186
        prevzipnode->nextfile = curzipnode->nextfile;
-
 
187
        free(curzipnode); /* free the item */
-
 
188
        curzipnode = prevzipnode->nextfile;
-
 
189
      }
-
 
190
      continue; /* go to the next item */
-
 
191
    }
-
 
192
 
147
 
193
    /* validate that the file has a valid filename (8+3, no shady chars...) */
148
    /* validate that the file has a valid filename (8+3, no shady chars...) */
194
    if (validfilename(curzipnode->filename) != 0) {
149
    if (validfilename(curzipnode->filename) != 0) {
195
      puts(svarlang_str(3, 23)); /* "ERROR: Package contains an invalid filename:" */
150
      puts(svarlang_str(3, 23)); /* "ERROR: Package contains an invalid filename:" */
196
      printf(" %s\n", curzipnode->filename);
151
      printf(" %s\n", curzipnode->filename);
197
      goto RAII_ERR;
152
      goto RAII_ERR;
198
    }
153
    }
199
 
154
 
200
    /* look out for collisions with already existing files (unless we are
155
    /* remove 'directory' ZIP entries to avoid false alerts about directory already existing */
201
     * updating the package and the local file belongs to it */
156
    if ((curzipnode->flags & ZIP_FLAG_ISADIR) != 0) goto DELETE_ZIP_NODE;
-
 
157
 
202
    shortfile = computelocalpath(curzipnode->filename, fname, dosdir, dirlist);
158
    /* is it a "link file"? remove it - FreeDOS-style link files are not supported */
203
    strcat(fname, shortfile);
-
 
204
    if ((findfileinlist(flist, fname) == NULL) && (fileexists(fname) != 0)) {
159
    if (strstr(curzipnode->filename, "links\\") == curzipnode->filename) goto DELETE_ZIP_NODE;
205
      puts(svarlang_str(3, 9)); /* "ERROR: Package contains a file that already exists locally:" */
-
 
206
      printf(" %s\n", fname);
-
 
207
      goto RAII_ERR;
-
 
208
    }
-
 
209
 
160
 
210
    /* abort if any entry is encrypted */
161
    /* abort if entry is encrypted */
211
    if ((curzipnode->flags & ZIP_FLAG_ENCRYPTED) != 0) {
162
    if ((curzipnode->flags & ZIP_FLAG_ENCRYPTED) != 0) {
212
      puts(svarlang_str(3, 20)); /* "ERROR: Package contains an encrypted file:" */
163
      puts(svarlang_str(3, 20)); /* "ERROR: Package contains an encrypted file:" */
213
      printf(" %s\n", curzipnode->filename);
164
      printf(" %s\n", curzipnode->filename);
214
      goto RAII_ERR;
165
      goto RAII_ERR;
215
    }
166
    }
216
 
167
 
217
    /* abort if any file is compressed with an unsupported method */
168
    /* abort if file is compressed with an unsupported method */
218
    if ((curzipnode->compmethod != ZIP_METH_STORE) && (curzipnode->compmethod != ZIP_METH_DEFLATE)) { /* unsupported compression method */
169
    if ((curzipnode->compmethod != ZIP_METH_STORE) && (curzipnode->compmethod != ZIP_METH_DEFLATE)) { /* unsupported compression method */
219
      kitten_printf(8, 2, curzipnode->compmethod); /* "ERROR: Package contains a file compressed with an unsupported method (%d):" */
170
      kitten_printf(8, 2, curzipnode->compmethod); /* "ERROR: Package contains a file compressed with an unsupported method (%d):" */
220
      puts("");
171
      puts("");
221
      printf(" %s\n", curzipnode->filename);
172
      printf(" %s\n", curzipnode->filename);
222
      goto RAII_ERR;
173
      goto RAII_ERR;
223
    }
174
    }
224
 
175
 
-
 
176
    /* is it the appinfo file? detach it from the list for now */
-
 
177
    if (strstr(curzipnode->filename, "appinfo\\") == curzipnode->filename) {
-
 
178
      if (appinfoptr != NULL) {
-
 
179
        puts(svarlang_str(3, 12)); /* "ERROR: This is not a valid SvarDOS package" */
-
 
180
        goto RAII_ERR;
-
 
181
      }
-
 
182
      appinfoptr = curzipnode;
-
 
183
      curzipnode = curzipnode->nextfile;
225
    /* add node to list */
184
      if (prevzipnode == NULL) {
-
 
185
        ziplinkedlist = curzipnode;
-
 
186
      } else {
-
 
187
        prevzipnode->nextfile = curzipnode;
-
 
188
      }
-
 
189
      continue;
-
 
190
    }
-
 
191
 
-
 
192
    /* all good, move to the next item in the list */
226
    prevzipnode = curzipnode;
193
    prevzipnode = curzipnode;
227
    curzipnode = curzipnode->nextfile;
194
    curzipnode = curzipnode->nextfile;
-
 
195
    continue;
-
 
196
 
-
 
197
    DELETE_ZIP_NODE:
-
 
198
    if (prevzipnode == NULL) {  /* take the item out of the list */
-
 
199
      ziplinkedlist = curzipnode->nextfile;
-
 
200
      free(curzipnode); /* free the item */
-
 
201
      curzipnode = ziplinkedlist;
-
 
202
    } else {
-
 
203
      prevzipnode->nextfile = curzipnode->nextfile;
-
 
204
      free(curzipnode); /* free the item */
-
 
205
      curzipnode = prevzipnode->nextfile;
-
 
206
    }
-
 
207
    /* go to the next item */
228
  }
208
  }
229
 
209
 
230
  /* if appinfo file not found, this is not a real SvarDOS package */
210
  /* if appinfo file not found, this is not a SvarDOS package */
231
  if (appinfoptr == NULL) {
211
  if (appinfoptr == NULL) {
232
    kitten_printf(3, 12, appinfofile); /* "ERROR: Package do not contain the %s file! Not a valid SvarDOS package." */
212
    puts(svarlang_str(3, 12)); /* "ERROR: This is not a valid SvarDOS package." */
233
    puts("");
-
 
234
    goto RAII_ERR;
213
    goto RAII_ERR;
235
  }
214
  }
236
 
215
 
237
  /* attach the appinfo node to the top of the list (installation second stage
216
  /* attach the appinfo node to the top of the list (installation second stage
238
   * relies on this) */
217
   * relies on this) */
239
  appinfoptr->nextfile = ziplinkedlist;
218
  appinfoptr->nextfile = ziplinkedlist;
240
  ziplinkedlist = appinfoptr;
219
  ziplinkedlist = appinfoptr;
241
 
220
 
-
 
221
  /* fill in pkgname based on what was found in APPINFO */
-
 
222
  {
-
 
223
    unsigned short i;
-
 
224
    /* copy and stop at the nearest dot */
-
 
225
    for (i = 0; i < 8; i++) {
-
 
226
      if (appinfoptr->filename[8 + i] == '.') break;
-
 
227
      pkgname[i] = appinfoptr->filename[8 + i];
-
 
228
    }
-
 
229
    pkgname[i] = 0;
-
 
230
    if ((i == 0) || (strcmp(appinfoptr->filename + 8 + i, ".lsm") != 0)) {
-
 
231
      puts(svarlang_str(3, 12)); /* "ERROR: This is not a valid SvarDOS package." */
-
 
232
      goto RAII_ERR;
-
 
233
    }
-
 
234
  }
-
 
235
 
-
 
236
  /* if updating, load the list of files belonging to the current package */
-
 
237
  if ((flags & PKGINST_UPDATE) != 0) {
-
 
238
    flist = pkg_loadflist(pkgname, dosdir);
-
 
239
  } else {
-
 
240
    /* if NOT updating, check that package is not installed already */
-
 
241
    if (validate_package_not_installed(pkgname, dosdir) != 0) goto RAII_ERR;
-
 
242
  }
-
 
243
 
-
 
244
  /* Verify that there's no collision with existing local files, but skip the
-
 
245
   * first entry as it is the appinfo (LSM) file that is handled specially */
-
 
246
 
-
 
247
  for (curzipnode = ziplinkedlist->nextfile; curzipnode != NULL; curzipnode = curzipnode->nextfile) {
-
 
248
 
-
 
249
    /* look out for collisions with already existing files (unless we are
-
 
250
     * updating the package and the local file belongs to it */
-
 
251
    shortfile = computelocalpath(curzipnode->filename, fname, dosdir, dirlist);
-
 
252
    strcat(fname, shortfile);
-
 
253
    if ((findfileinlist(flist, fname) == NULL) && (fileexists(fname) != 0)) {
-
 
254
      puts(svarlang_str(3, 9)); /* "ERROR: Package contains a file that already exists locally:" */
-
 
255
      printf(" %s\n", fname);
-
 
256
      goto RAII_ERR;
-
 
257
    }
-
 
258
  }
-
 
259
 
242
  goto RAII;
260
  goto RAII;
243
 
261
 
244
  RAII_ERR:
262
  RAII_ERR:
245
  zip_freelist(&ziplinkedlist);
263
  zip_freelist(&ziplinkedlist);
246
  ziplinkedlist = NULL;
264
  ziplinkedlist = NULL;