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;
|