Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 1677 → Rev 1678

/pkg/trunk/helpers.c
1,6 → 1,6
/*
* This file is part of pkg (SvarDOS package manager)
* Copyright (C) 2012-2022 Mateusz Viste
* Copyright (C) 2012-2024 Mateusz Viste
*
* It contains a few helper function...
*/
26,6 → 26,20
}
 
 
/* trim CRC from a filename and returns a pointer to the CRC part.
* this is used to parse filename lines from LSM files */
char *trimfnamecrc(char *fname) {
while (*fname) {
if (*fname == '?') {
*fname = 0;
return(fname + 1);
}
fname++;
}
return(0);
}
 
 
void removeDoubleBackslashes(char *str) {
char *curpos;
int x;
/pkg/trunk/helpers.h
1,6 → 1,6
/*
* This file is part of pkginst
* Copyright (C) 2012-2022 Mateusz Viste
* Copyright (C) 2012-2024 Mateusz Viste
*
* It contains a few helper function...
*/
7,12 → 7,24
 
#ifndef helpers_sentinel
#define helpers_sentinel
 
#include "loadconf.h" /* required for the customdirs struct */
 
void slash2backslash(char *str);
 
/* trim CRC from a filename and returns a pointer to the CRC part.
* this is used to parse filename lines from LSM files */
char *trimfnamecrc(char *fname);
 
char *fdnpkg_strcasestr(const char *s, const char *find);
 
/* recursively mkdir() directories of a path.
* ignores the trailing filename if there is one */
void mkpath(char *dirs);
 
char *computelocalpath(char *longfilename, char *respath, const char *dosdir, const struct customdirs *dirlist);
void removeDoubleBackslashes(char *str);
char *getfext(char *fname);
int freadtokval(FILE *fd, char *line, size_t maxlen, char **val, char delim);
 
#endif
/pkg/trunk/pkg.lsm
1,2 → 1,2
version: 20240118
version: 20240201
description: SvarDOS package manager installs, removes and updates packages
/pkg/trunk/pkginst.c
1,6 → 1,6
/*
* This file is part of pkg (SvarDOS)
* Copyright (C) 2012-2023 Mateusz Viste
* Copyright (C) 2012-2024 Mateusz Viste
*/
 
#include <ctype.h> /* toupper() */
67,8 → 67,8
 
/* returns 0 if pkgname is not installed, non-zero otherwise */
int is_package_installed(const char *pkgname, const char *dosdir) {
char fname[512];
sprintf(fname, "%s\\packages\\%s.lst", dosdir, pkgname);
char fname[256];
sprintf(fname, "%s\\appinfo\\%s.lsm", dosdir, pkgname);
return(fileexists(fname)); /* file exists -> package is installed */
}
 
94,12 → 94,16
}
 
 
/* prepare a package for installation. this is mandatory before actually installing it!
* returns a pointer to the zip file's index on success, NULL on failure. the **zipfd pointer is updated with a file descriptor to the open zip file to install. */
/* prepare a package for installation. this is mandatory before installing it!
* returns a pointer to the zip file's index on success, NULL on failure.
* the **zipfd pointer is updated with file descriptor of the open (to be
* installed) zip file.
* the returned ziplist is guaranteed to have the APPINFO file as first node
* the ziplist is also guaranteed not to contain any directory entries */
struct ziplist *pkginstall_preparepackage(const char *pkgname, const char *zipfile, int flags, FILE **zipfd, const char *dosdir, const struct customdirs *dirlist) {
char fname[256];
char appinfofile[256];
int appinfopresence;
char appinfofile[32];
struct ziplist *appinfoptr;
char *shortfile;
struct ziplist *ziplinkedlist = NULL, *curzipnode, *prevzipnode;
struct flist_t *flist = NULL;
121,7 → 125,7
if ((slen < 4) || (fname[slen - 4] != '.')) strcat(fname, ".SVP");
}
 
/* Now let's check the content of the zip file */
/* now let's check the content of the zip file */
 
*zipfd = fopen(fname, "rb");
if (*zipfd == NULL) {
137,9 → 141,11
if ((flags & PKGINST_UPDATE) != 0) {
flist = pkg_loadflist(pkgname, dosdir);
}
 
/* Verify that there's no collision with existing local files, look for the appinfo presence */
appinfopresence = 0;
appinfoptr = NULL;
prevzipnode = NULL;
 
for (curzipnode = ziplinkedlist; curzipnode != NULL;) {
/* change all slashes to backslashes, and switch into all-lowercase */
slash2backslash(curzipnode->filename);
149,10 → 155,18
curzipnode->filename[0] = 0; /* mark it "empty", will be removed in a short moment */
}
/* is it a "link file"? skip it - link files are no longer supported */
if (fdnpkg_strcasestr(curzipnode->filename, "links\\") == curzipnode->filename) {
if (strstr(curzipnode->filename, "links\\") == curzipnode->filename) {
curzipnode->filename[0] = 0; /* in fact, I just mark the file as 'empty' on the filename - see later below */
}
 
/* is it the appinfo file? remember it and keep it separate from the list for now */
if (strcmp(curzipnode->filename, appinfofile) == 0) {
appinfoptr = curzipnode;
curzipnode = curzipnode->nextfile;
if (prevzipnode != NULL) prevzipnode->nextfile = curzipnode;
continue;
}
 
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) */
if (prevzipnode == NULL) { /* take the item out of the list */
ziplinkedlist = curzipnode->nextfile;
165,6 → 179,7
}
continue; /* go to the next item */
}
 
/* validate that the file has a valid filename (8+3, no shady chars...) */
if (validfilename(curzipnode->filename) != 0) {
puts(svarlang_str(3, 23)); /* "ERROR: Package contains an invalid filename:" */
171,6 → 186,7
printf(" %s\n", curzipnode->filename);
goto RAII_ERR;
}
 
/* look out for collisions with already existing files (unless we are
* updating the package and the local file belongs to it */
shortfile = computelocalpath(curzipnode->filename, fname, dosdir, dirlist);
180,6 → 196,7
printf(" %s\n", fname);
goto RAII_ERR;
}
 
/* abort if any entry is encrypted */
if ((curzipnode->flags & ZIP_FLAG_ENCRYPTED) != 0) {
puts(svarlang_str(3, 20)); /* "ERROR: Package contains an encrypted file:" */
186,6 → 203,7
printf(" %s\n", curzipnode->filename);
goto RAII_ERR;
}
 
/* abort if any file is compressed with an unsupported method */
if ((curzipnode->compmethod != ZIP_METH_STORE) && (curzipnode->compmethod != ZIP_METH_DEFLATE)) { /* unsupported compression method */
kitten_printf(8, 2, curzipnode->compmethod); /* "ERROR: Package contains a file compressed with an unsupported method (%d):" */
193,17 → 211,24
printf(" %s\n", curzipnode->filename);
goto RAII_ERR;
}
if (strcmp(curzipnode->filename, appinfofile) == 0) appinfopresence = 1;
 
/* add node to list */
prevzipnode = curzipnode;
curzipnode = curzipnode->nextfile;
}
 
/* if appinfo file not found, this is not a real SvarDOS package */
if (appinfopresence != 1) {
if (appinfoptr == NULL) {
kitten_printf(3, 12, appinfofile); /* "ERROR: Package do not contain the %s file! Not a valid SvarDOS package." */
puts("");
goto RAII_ERR;
}
 
/* attach the appinfo node to the top of the list (installation second stage
* relies on this) */
appinfoptr->nextfile = ziplinkedlist;
ziplinkedlist = appinfoptr;
 
goto RAII;
 
RAII_ERR:
262,37 → 287,49
int pkginstall_installpackage(const char *pkgname, const char *dosdir, const struct customdirs *dirlist, struct ziplist *ziplinkedlist, FILE *zipfd) {
char buff[256];
char fulldestfilename[256];
char packageslst[32];
char *shortfile;
long filesextractedsuccess = 0, filesextractedfailure = 0;
struct ziplist *curzipnode;
FILE *lstfd;
FILE *lsmfd;
int unzip_result;
 
sprintf(packageslst, "packages\\%s.lst", pkgname); /* Prepare the packages/xxxx.lst filename string for later use */
 
/* create the %DOSDIR%/packages directory, just in case it doesn't exist yet */
sprintf(buff, "%s\\packages\\", dosdir);
/* create the %DOSDIR%/APPINFO directory, just in case it doesn't exist yet */
sprintf(buff, "%s\\appinfo\\%s.lsm", dosdir, pkgname);
mkpath(buff);
 
/* open the lst file */
sprintf(buff, "%s\\%s", dosdir, packageslst);
lstfd = fopen(buff, "wb"); /* opening it in binary mode, because I like to have control over line terminators (CR/LF) */
if (lstfd == NULL) {
/* start by extracting the APPINFO (LSM) file - I need it so I can append the
* list of files belonging to the packages later */
unzip_result = zip_unzip(zipfd, ziplinkedlist, buff);
if (unzip_result != 0) {
kitten_printf(8, 3, ziplinkedlist, buff); /* "ERROR: failed extracting '%s' to '%s'!" */
printf(" [%d]\n", unzip_result);
return(-1);
}
printf(" %s -> %s\n", ziplinkedlist->filename, buff);
filesextractedsuccess++;
 
/* open the (freshly created) LSM file */
lsmfd = fopen(buff, "ab"); /* opening in APPEND mode so I do not loose the LSM content */
if (lsmfd == NULL) {
kitten_printf(3, 10, buff); /* "ERROR: Could not create %s!" */
puts("");
return(-2);
}
fprintf(lsmfd, "\r\n"); /* in case the LSM does not end with a clear line already */
 
/* write list of files in zip into the lst, and create the directories structure */
for (curzipnode = ziplinkedlist; curzipnode != NULL; curzipnode = curzipnode->nextfile) {
int unzip_result;
if ((curzipnode->flags & ZIP_FLAG_ISADIR) != 0) continue; /* skip directories */
shortfile = computelocalpath(curzipnode->filename, buff, dosdir, dirlist); /* substitute paths to custom dirs */
/* log the filename to packages\pkg.lst */
fprintf(lstfd, "%s%s\r\n", buff, shortfile);
for (curzipnode = ziplinkedlist->nextfile; curzipnode != NULL; curzipnode = curzipnode->nextfile) {
 
/* substitute paths to custom dirs */
shortfile = computelocalpath(curzipnode->filename, buff, dosdir, dirlist);
 
/* log the filename to LSM metadata file + its CRC */
fprintf(lsmfd, "%s%s?%08lX\r\n", buff, shortfile, curzipnode->crc32);
 
/* create the path, just in case it doesn't exist yet */
mkpath(buff);
sprintf(fulldestfilename, "%s%s", buff, shortfile);
 
/* Now unzip the file */
unzip_result = zip_unzip(zipfd, curzipnode, fulldestfilename);
if (unzip_result != 0) {
304,7 → 341,7
filesextractedsuccess += 1;
}
}
fclose(lstfd);
fclose(lsmfd);
 
kitten_printf(3, 19, pkgname, filesextractedsuccess, filesextractedfailure); /* "Package %s installed: %ld files extracted, %ld errors." */
puts("");
/pkg/trunk/pkginst.h
1,6 → 1,6
/*
* This file is part of SvarDOS
* Copyright (C) 2012-2021 Mateusz Viste
* Copyright (C) 2012-2024 Mateusz Viste
*/
 
#ifndef pkginst_sentinel
/pkg/trunk/pkgrem.c
1,6 → 1,6
/*
* This file is part of the pkg (SvarDOS) project.
* Copyright (C) Mateusz Viste 2012-2022
* Copyright (C) Mateusz Viste 2012-2024
*/
 
#include <ctype.h> /* toupper() */
70,21 → 70,36
int lastdirsep;
struct dirliststruct *dirlist = NULL; /* used to remember directories to remove */
 
/* open the file %DOSDIR%\packages\pkgname.lst */
/* open the (legacy) listing file at %DOSDIR%\packages\pkgname.lst
* if not exists then fall back to appinfo\pkgname.lsm */
sprintf(fpath, "%s\\packages\\%s.lst", dosdir, pkgname);
flist = fopen(fpath, "rb");
if (flist == NULL) {
kitten_printf(4, 0, pkgname); /* "Package %s is not installed, so not removed." */
puts("");
return(-1);
sprintf(fpath, "%s\\appinfo\\%s.lsm", dosdir, pkgname);
flist = fopen(fpath, "rb");
if (flist == NULL) {
kitten_printf(4, 0, pkgname); /* "Package %s is not installed, so not removed." */
puts("");
return(-1);
}
}
 
/* remove all files/folders listed in pkgname.lst but NOT pkgname.lst */
/* remove all files/folders listed in pkgname.lsm but NOT pkgname.lsm */
while (freadtokval(flist, buff, sizeof(buff), NULL, 0) == 0) {
int x;
slash2backslash(buff); /* change all slash to backslash */
if (buff[0] == 0) continue; /* skip empty lines */
 
/* skip empty lines */
if (buff[0] == 0) continue;
 
/* change all slash to backslash */
slash2backslash(buff);
 
/* skip garbage */
if ((buff[1] != ':') || (buff[2] != '\\')) continue;
 
/* trim out CRC information (if present) */
trimfnamecrc(buff);
 
/* remember the path part for removal later */
lastdirsep = -1;
for (x = 1; buff[x] != 0; x++) {
99,7 → 114,8
/* if it's a directory, skip it */
if (buff[strlen(buff) - 1] == '\\') continue;
 
/* do not delete pkgname.lst at this point - I am using it (will be deleted later) */
/* do not delete pkgname.lst at this point because I am using it (will be
* deleted later) */
if (strcasecmp(buff, fpath) == 0) continue;
 
/* remove it */
108,7 → 124,7
unlink(buff);
}
 
/* close the lst file */
/* close the lsm file */
fclose(flist);
 
/* iterate over dirlist and remove directories if empty, from longest to shortest */
135,7 → 151,10
}
 
/* remove the lst file */
kitten_printf(4, 4, fpath); /* "removing %s" */
puts("");
unlink(fpath);
 
kitten_printf(4, 5, pkgname); /* "Package %s has been removed." */
puts("");
return(0);
/pkg/trunk/pkgrem.h
1,9 → 1,11
/*
* This file is part of the SvarDOS project.
* Copyright (C) Mateusz Viste 2012-2021
* Copyright (C) Mateusz Viste 2012-2024
*/
 
#ifndef pkgrem_sentinel
#define pkgrem_sentinel
 
int pkgrem(const char *pkgname, const char *dosdir);
 
#endif
/pkg/trunk/showinst.c
1,6 → 1,6
/*
* This file is part of PKG (SvarDOS)
* Copyright (C) 2013-2022 Mateusz Viste
* Copyright (C) 2013-2024 Mateusz Viste
*/
 
#include <stdio.h>
26,7 → 26,7
char ver[16];
int matchfound = 0;
 
sprintf(buff, "%s\\packages", dosdir);
sprintf(buff, "%s\\appinfo", dosdir);
dp = opendir(buff);
if (dp == NULL) {
kitten_printf(9, 0, buff); /* "ERROR: Could not access directory %s" */
38,11 → 38,11
int tlen = strlen(ep->d_name);
if (ep->d_name[0] == '.') continue; /* ignore '.', '..', and hidden directories */
if (tlen < 4) continue; /* files must be at least 5 bytes long ("x.lst") */
if (strcasecmp(ep->d_name + tlen - 4, ".lst") != 0) continue; /* if not an .lst file, skip it silently */
ep->d_name[tlen - 4] = 0; /* trim out the ".lst" suffix */
if (strcasecmp(ep->d_name + tlen - 4, ".lsm") != 0) continue; /* if not an .lsm file, skip it silently */
ep->d_name[tlen - 4] = 0; /* trim out the ".lsm" suffix */
 
if (filterstr != NULL) {
if (fdnpkg_strcasestr(ep->d_name, filterstr) == NULL) continue; /* if it's not matching the non-NULL filter, skip it */
if (fdnpkg_strcasestr(ep->d_name, filterstr) == NULL) continue; /* skip if not matching the non-NULL filter */
}
 
/* load the metadata from %DOSDIR\APPINFO\*.lsm */
79,15 → 79,32
sprintf(buff, "%s\\packages\\%s.lst", dosdir, pkgname);
fd = fopen(buff, "rb");
if (fd == NULL) {
kitten_printf(9, 1, pkgname); /* "ERROR: Local package '%s' not found." */
puts("");
return(NULL);
sprintf(buff, "%s\\appinfo\\%s.lsm", dosdir, pkgname);
fd = fopen(buff, "rb");
if (fd == NULL) {
kitten_printf(9, 1, pkgname); /* "ERROR: Local package '%s' not found." */
puts("");
return(NULL);
}
}
 
/* iterate through all lines of the file */
while (freadtokval(fd, buff, sizeof(buff), NULL, 0) == 0) {
slash2backslash(buff); /* change all / to \ */
if (buff[0] == 0) continue; /* skip empty lines */
if (buff[strlen(buff) - 1] == '\\') continue; /* skip directories */
/* skip empty lines */
if (buff[0] == 0) continue;
 
/* normalize slashes to backslashes */
slash2backslash(buff);
 
/* skip garbage */
if ((buff[1] != ':') || (buff[2] != '\\')) continue;
 
/* skip directories */
if (buff[strlen(buff) - 1] == '\\') continue;
 
/* trim ? trailer (may contain the file's CRC) */
trimfnamecrc(buff);
 
/* add the new node to the result */
newnode = malloc(sizeof(struct flist_t) + strlen(buff));
if (newnode == NULL) {
/pkg/trunk/version.h
4,7 → 4,7
#ifndef COMMON_H_SENTINEL
#define COMMON_H_SENTINEL
 
#define PVER "20240118"
#define PVER "20240201"
#define PDATE "2012-2024"
 
#endif