Patches: inline 'binaries', feature requirements, tmp file fix
Ludwig Nussel
ludwig.nussel at gmx.de
Sun Sep 19 17:40:56 EDT 2004
Hi,
loki_setup-binaryinline.diff - New attribute 'inline' for 'binary'
elements. Can be used to put start scripts directly in the
xml file. It's kind of a hack, it first saves the content to
a file an then calls the normal copy_file() to do the job.
loki_setup-feature.diff - Allows to specify features that the
installer must have to be able to install the xml file.
loki_uninstall-tmpfix.diff - loki-uninstall appends error messages
to /tmp/uninstall.log. No idea what's that good for except
for inviting someone to place an evil symlink.
cu
Ludwig
--
(o_ Ludwig.Nussel at gmx.de
//\ PGP Key ID: FF8135CE
V_/_ ICQ: 52166811
-------------- next part --------------
Index: loki_setup/file.h
===================================================================
--- loki_setup.orig/file.h
+++ loki_setup/file.h
@@ -55,4 +55,12 @@ extern int dir_exists(const char *path);
extern void file_create_hierarchy(install_info *info, const char *path);
extern void dir_create_hierarchy(install_info *info, const char *path, int mode);
extern int dir_is_accessible(const char *path);
+
+/** create a temporary directory and return it's name. Failure to create the
+ * directory will abort the program. It is only allowed to created inodes that
+ * can be removed with unlink() in that directory */
+extern const char* tmpdir();
+
+/** clean all files in the temporary directory and remove it */
+extern int cleantmpdir();
#endif
Index: loki_setup/main.c
===================================================================
--- loki_setup.orig/main.c
+++ loki_setup/main.c
@@ -75,6 +75,7 @@ void exit_setup(int ret)
FreePlugins();
free_corrupt_files();
unmount_filesystems();
+ cleantmpdir();
log_exit();
exit(ret);
}
Index: loki_setup/file.c
===================================================================
--- loki_setup.orig/file.c
+++ loki_setup/file.c
@@ -11,6 +11,7 @@
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
+#include <time.h>
#include <zlib.h>
@@ -783,3 +784,71 @@ static void dobz2init()
}
#endif
+
+static char tmpdirname[PATH_MAX] = "\0";
+
+const char* tmpdir()
+{
+ unsigned count;
+
+ if(*tmpdirname)
+ return tmpdirname;
+
+ srand(time(NULL));
+ for(count = 0; count < 1000; ++count)
+ {
+ snprintf(tmpdirname, sizeof(tmpdirname), "/tmp/setuptmp.%06X", rand());
+ if(mkdir(tmpdirname, 0700) == 0)
+ {
+ log_debug("temporary directory %s created", tmpdirname);
+ return tmpdirname;
+ }
+ }
+ log_fatal(_("Unable to create temporary directory: %s"), strerror(errno));
+
+ return NULL;
+}
+
+int cleantmpdir()
+{
+ DIR* dir;
+ struct dirent *entry;
+ char cwd[PATH_MAX];
+
+ if(!*tmpdirname)
+ return 0;
+
+ if(!getcwd(cwd, sizeof(cwd)))
+ cwd[0] = '\0';
+
+ if(chdir(tmpdirname) == -1)
+ {
+ log_warning(_("Can not chdir to temporary directory: %s"), strerror(errno));
+ return -1;
+ }
+
+ dir = opendir(tmpdirname);
+ if(!dir)
+ {
+ log_warning(_("Can not open temporary directory: %s"), strerror(errno));
+ return -1;
+ }
+
+ while((entry = readdir(dir)) != NULL)
+ {
+ if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
+ continue;
+
+ log_debug("unlink temporary file %s", entry->d_name);
+ if(unlink(entry->d_name) == -1)
+ log_warning(_("Can not remove %s/%s: %s"), tmpdirname, entry->d_name, strerror(errno));
+ }
+
+ closedir(dir);
+
+ if(*cwd)
+ chdir(cwd);
+
+ return rmdir(tmpdirname);
+}
+
Index: loki_setup/copy.c
===================================================================
--- loki_setup.orig/copy.c
+++ loki_setup/copy.c
@@ -108,6 +108,8 @@ typedef struct _corrupt_list {
static corrupt_list *corrupts = NULL;
+static void copy_binary_finish(install_info* info, xmlNodePtr node, const char* fn, struct file_elem *file);
+
void add_corrupt_file(const product_t *prod, const char *path, const char *option)
{
corrupt_list *item;
@@ -585,6 +587,50 @@ ssize_t copy_manpage(install_info *info,
return copied;
}
+/** write memory 'data' with length 'len' to a temporary file called 'name'.
+ * The full path to the created file is returned in name_out which must hold at
+ * least PATH_MAX characters.
+ * @return pointer to name_out for convenience. On error NULL is returned.
+ * content of name_out is undefined in this case.
+ */
+static char* write_temp_script(const char* name, char* name_out,
+ const char* data,
+ size_t len)
+{
+ int fd;
+ ssize_t ret;
+
+ if(!name_out)
+ return NULL;
+
+ if(strrchr(name, '/'))
+ {
+ log_warning("'name' must not contain slashes");
+ return NULL;
+ }
+
+ name_out[PATH_MAX-1] = '\0';
+ name_out[PATH_MAX-2] = '\0';
+ strncpy(name_out, tmpdir(), PATH_MAX-2);
+ name_out[strlen(name_out)] = '/';
+ strncpy(name_out+strlen(name_out), name, PATH_MAX-strlen(name_out)-1);
+
+ if((fd = open(name_out, O_WRONLY|O_CREAT, 0755)) == -1)
+ {
+ log_warning(_("Could not create temporary script: %s"), strerror(errno));
+ return NULL;
+ }
+
+ ret = write(fd, data, len);
+ if(ret < 0 || (unsigned)ret != len)
+ {
+ log_warning(_("Could not create temporary script: %s"), strerror(errno));
+ name_out = NULL;
+ }
+ close(fd);
+ return name_out;
+}
+
ssize_t copy_binary(install_info *info, xmlNodePtr node, const char *filedesc, const char *dest,
const char *from_cdrom,
int (*update)(install_info *info, const char *path, size_t progress, size_t size, const char *current))
@@ -617,6 +663,36 @@ ssize_t copy_binary(install_info *info,
copied = 0;
size = 0;
+ if(xmlNodePropIsTrue(node, "inline"))
+ {
+ if(!binpath)
+ {
+ log_warning(_("'binpath' attribute is mandatory for inline 'binary' tag"));
+ goto copy_binary_exit;
+ }
+ else if(strrchr(binpath, '/'))
+ {
+ log_warning(_("'binpath' attribute must not contain slashes for inline 'binary' tag"));
+ goto copy_binary_exit;
+ }
+
+ strncpy(fdest, dest, sizeof(fdest));
+ fdest[sizeof(fdest)-1] = '\0';
+
+ if(!write_temp_script(binpath, bin, filedesc, strlen(filedesc)))
+ goto copy_binary_exit;
+
+ copied = copy_file(info, NULL, bin, fdest, final, 1, 1, node, update, &file);
+ if(copied > 0)
+ {
+ size += copied;
+
+ copy_binary_finish(info, node, final, file);
+ }
+ unlink(bin);
+ goto copy_binary_exit;
+ }
+
while ( filedesc && parse_line(&filedesc, final, (sizeof final)) ) {
if (! in_rpm) {
const char *cdpath = NULL;
@@ -716,23 +792,9 @@ ssize_t copy_binary(install_info *info,
log_warning(_("Unable to copy file '%s'"), fpat);
ui_fatal_error(_("Unable to copy file '%s'"), fpat);
} else if ( copied > 0 || in_rpm ) {
- char *symlink = xmlGetProp(node, "symlink");
- char sym_to[PATH_MAX];
-
size += copied;
- /* Create the symlink */
- if ( *info->symlinks_path && symlink ) {
- snprintf(sym_to, sizeof(sym_to), "%s/%s", info->symlinks_path, symlink);
- file_symlink(info, final, sym_to);
- }
- add_bin_entry(info, current_option, file, symlink,
- xmlGetProp(node, "desc"),
- xmlGetProp(node, "menu"),
- xmlGetProp(node, "name"),
- xmlGetProp(node, "icon"),
- xmlGetProp(node, "args"),
- xmlGetProp(node, "play")
- );
+
+ copy_binary_finish(info, node, final, file);
}
}
copy_binary_exit:
@@ -740,6 +802,29 @@ ssize_t copy_binary(install_info *info,
return size;
}
+/** to be called when binary was successfully installed. creates optional
+ * symlink and registers the file in the setup database.
+ */
+static void copy_binary_finish(install_info* info, xmlNodePtr node, const char* fn, struct file_elem *file)
+{
+ char *symlink = xmlGetProp(node, "symlink");
+ char sym_to[PATH_MAX];
+
+ /* Create the symlink */
+ if ( *info->symlinks_path && symlink ) {
+ snprintf(sym_to, sizeof(sym_to), "%s/%s", info->symlinks_path, symlink);
+ file_symlink(info, fn, sym_to);
+ }
+ add_bin_entry(info, current_option, file, symlink,
+ xmlGetProp(node, "desc"),
+ xmlGetProp(node, "menu"),
+ xmlGetProp(node, "name"),
+ xmlGetProp(node, "icon"),
+ xmlGetProp(node, "args"),
+ xmlGetProp(node, "play")
+ );
+}
+
static int copy_script(install_info *info, xmlNodePtr node, const char *script, const char *dest, size_t size,
int (*update)(install_info *info, const char *path, size_t progress, size_t size, const char *current), const char *from_cdrom, const char *msg)
{
@@ -1196,7 +1281,8 @@ unsigned long long size_node(install_inf
size += size_list(info, from_cdrom, srcpath,
xmlNodeListGetString(info->config, node->childs, 1));
} else if ( strcmp(node->name, "binary") == 0 ) {
- size += size_binary(info, from_cdrom,
+ if(!xmlNodePropIsTrue(node, "inline"))
+ size += size_binary(info, from_cdrom,
xmlNodeListGetString(info->config, node->childs, 1));
} else if ( strcmp(node->name, "manpage") == 0 ) {
size += size_manpage(info, node, from_cdrom);
@@ -1257,3 +1343,4 @@ int has_binaries(install_info *info, xml
}
+
Index: loki_setup/README.xml
===================================================================
--- loki_setup.orig/README.xml
+++ loki_setup/README.xml
@@ -652,6 +652,10 @@ There are several optional attributes of
args Specify optional arguments to be added on the command line when running the binary.
+ inline When set to 'yes' the text content of the element is used as script
+ content instead of a path. The value of 'binarypath' is used as
+ script name in this case
+
The FILES element:
The files element contains a list of files and directories, one per line,
-------------- next part --------------
Index: loki_setup/install.c
===================================================================
--- loki_setup.orig/install.c
+++ loki_setup/install.c
@@ -129,6 +129,32 @@ int disable_binary_path = 0;
static int install_updatemenus_script = 0;
static int uninstall_generated = 0;
+typedef struct
+{
+ const char* name;
+ unsigned version;
+} SetupFeature;
+
+/** features supported by this installer */
+static SetupFeature features[] =
+{
+ { "inline-scripts", 1 },
+ { NULL, 0 }
+};
+
+static int have_feature(const char* name, unsigned version)
+{
+ SetupFeature* f;
+
+ for (f = features; f->name; ++f)
+ {
+ if(!strcmp(f->name, name) && f->version >= version)
+ return 1;
+ }
+
+ return 0;
+}
+
/* Functions to retrieve attribution information from the XML tree */
const char *GetProductName(install_info *info)
{
@@ -1241,13 +1267,15 @@ int CheckRequirements(install_info *info
match_arch(info, arch) &&
match_libc(info, libc) &&
match_distro(info, distro) ) {
- char *prop = xmlGetProp(node, "command");
+ char *commandprop = xmlGetProp(node, "command");
+ char *featureprop = xmlGetProp(node, "feature");
xmlFree(lang); xmlFree(arch); xmlFree(libc); xmlFree(distro);
- if ( !prop ) {
- log_fatal(_("XML: 'require' tag doesn't have a mandatory 'command' attribute"));
- } else {
+ if ( !commandprop && !featureprop ) {
+ log_fatal(_("XML: 'require' tag doesn't have a mandatory 'command' or 'feature' attribute"));
+ }
+ if(commandprop) {
/* Launch the command */
- if ( run_script(info, prop, 0, 0) != 0 ) {
+ if ( run_script(info, commandprop, 0, 0) != 0 ) {
/* We failed: print out error message */
text = xmlNodeListGetString(info->config, node->childs, 1);
if(text) {
@@ -1259,11 +1287,30 @@ int CheckRequirements(install_info *info
}
UI.prompt(buf, RESPONSE_OK);
}
- xmlFree(prop);
+ xmlFree(commandprop);
+ return 0;
+ }
+ xmlFree(commandprop);
+ } else if(featureprop) {
+ char *verprop = xmlGetProp(node, "version");
+ unsigned version = 1;
+ if(verprop) {
+ version = atoi(verprop);
+ xmlFree(verprop);
+ }
+ if(!have_feature(featureprop, version))
+ {
+ char buf[1024];
+ snprintf(buf, sizeof(buf),
+ _("The installer is not suitable for installing this product "
+ "(missing feature '%s' version '%u')"), featureprop, version);
+ UI.prompt(buf, RESPONSE_OK);
+ xmlFree(featureprop);
return 0;
}
- xmlFree(prop);
}
+
+ xmlFree(featureprop);
} else {
xmlFree(lang); xmlFree(arch); xmlFree(libc); xmlFree(distro);
}
@@ -2626,7 +2673,7 @@ int run_script(install_info *info, const
(to avoid problems with 'sh script.sh')
*/
working_dir[0] = '\0';
- if ( access(script, R_OK) == 0 ) {
+ if ( *script != '/' && access(script, R_OK) == 0 ) {
if ( getcwd(working_dir, sizeof(working_dir)) == NULL ) {
perror("run_script: getcwd");
}
Index: loki_setup/README.xml
===================================================================
--- loki_setup.orig/README.xml
+++ loki_setup/README.xml
@@ -326,10 +326,13 @@ are fulfilled.
are parsed in sequential order. Installation will abort if any of the specified commands return
a non-nil value.
-This element takes one mandatory attribute :
+This element takes either of the following mandatory attributes :
command Specify the command to be run to determine the condition. A nil value means success.
+ feature Specify the name of a feature that must be present in the
+ installer to be able to process this XML file.
+
This element takes some optional attributes :
lang Specify the language for the message. Used for localization. The command will be executed
only if the locale settings match.
@@ -345,13 +348,20 @@ This element takes some optional attribu
distro This component applies only to the specified OS distribution.
Look at the end of this file for a list of possible values.
-The text specified in the element will be displayed to the user if the condition fails.
-Example:
+ version [only for feature attribute] the minimum integer version number
+ required for the specified feature.
+
+The text specified in the element will be displayed to the user if the
+condition of the command attribute fails. It has no meaning for the feature
+attribute.
+Examples:
<require command="/bin/false">
This is always failing! Thus this message is always displayed.
</require>
+<require feature="inline-scripts" version="1"/>
+
The POST_INSTALL_MSG element :
This element displays an optional message to the user at the end of a successful installation.
-------------- next part --------------
Index: loki_setup/uninstall.c
===================================================================
--- loki_setup.orig/uninstall.c
+++ loki_setup/uninstall.c
@@ -58,12 +58,7 @@ static void print_usage(const char *argv
static void log_file(const char *name, const char *reason)
{
- FILE *log = fopen("/tmp/uninstall.log", "a");
fprintf(stderr, "%s : %s\n", name, reason);
- if(log) {
- fprintf(log, "%s : %s\n", name, reason);
- fclose(log);
- }
}
struct dir_entry {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://icculus.org/pipermail/lokisetup/attachments/20040919/44ab787d/attachment.pgp>
More information about the Lokisetup
mailing list