Hello community, here is the log from the commit of package linuxrc for openSUSE:Factory checked in at 2019-10-28 16:45:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/linuxrc (Old) and /work/SRC/openSUSE:Factory/.linuxrc.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "linuxrc" Mon Oct 28 16:45:33 2019 rev:274 rq:742160 version:7.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/linuxrc/linuxrc.changes 2019-09-27 14:44:19.821407266 +0200 +++ /work/SRC/openSUSE:Factory/.linuxrc.new.2990/linuxrc.changes 2019-10-28 16:45:48.996658917 +0100 @@ -1,0 +2,19 @@ +Wed Oct 23 13:46:25 UTC 2019 - wfe...@opensuse.org + +- merge gh#openSUSE/linuxrc#196 +- show debug info also on console device +- fix reading slp data +- show both autoyast and autoyast2 options on linuxrc info page +- support autoyast-style URL syntax +- read and parse autoyast file +- add needed entries to global config struct +- add new autoyast.parse key +- parse autoyast/autoyast2 options and add new autoyast url schemes +- activate new autoyast code +- fix parsing linuxrc options embedded in AutoYaST file (bsc#1145574) +- document autoyast option behavior +- small additions to autoyast handling doc +- support autoyast url schemes in linuxrc +- 7.0.0 + +-------------------------------------------------------------------- Old: ---- linuxrc-6.0.15.tar.xz New: ---- linuxrc-7.0.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ linuxrc.spec ++++++ --- /var/tmp/diff_new_pack.bXcVVm/_old 2019-10-28 16:45:49.596659680 +0100 +++ /var/tmp/diff_new_pack.bXcVVm/_new 2019-10-28 16:45:49.604659691 +0100 @@ -17,7 +17,7 @@ Name: linuxrc -Version: 6.0.15 +Version: 7.0.0 Release: 0 Summary: SUSE Installation Program License: GPL-3.0+ ++++++ linuxrc-6.0.15.tar.xz -> linuxrc-7.0.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/VERSION new/linuxrc-7.0.0/VERSION --- old/linuxrc-6.0.15/VERSION 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/VERSION 2019-10-23 15:46:25.000000000 +0200 @@ -1 +1 @@ -6.0.15 +7.0.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/auto2.c new/linuxrc-7.0.0/auto2.c --- old/linuxrc-6.0.15/auto2.c 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/auto2.c 2019-10-23 15:46:25.000000000 +0200 @@ -36,11 +36,13 @@ static int driver_is_active(hd_t *hd); static void auto2_progress(char *pos, char *msg); +static void auto2_read_repo_file(url_t *url, char *src, char *dst); static void auto2_read_repo_files(url_t *url); static void auto2_read_repomd_files(url_t *url); static char *auto2_splash_name(void); static int test_and_add_dud(url_t *url); +static void auto2_read_autoyast(url_t *url); /* @@ -364,31 +366,9 @@ } /* - * load autoyast file unless the user has specified an autoyast option - * -- ok this sounds weird but actually makes sense... + * load autoyast file; prefer autoyast option over autoyast2 */ - if(config.autoyast2 && !config.autoyast) { - url = url_set(config.autoyast2); - log_show_maybe(!url->quiet, "Downloading AutoYaST file: %s\n", config.autoyast2); - - err = url_read_file_anywhere(url, NULL, NULL, "/download/autoinst.xml", NULL, URL_FLAG_PROGRESS + URL_FLAG_NODIGEST); - url_umount(url); - url_free(url); - if(!err) { - log_info("setting AutoYaST option to file:///download/autoinst.xml\n"); - str_copy(&config.autoyast, "file:///download/autoinst.xml"); - /* parse it: - * you can embed linuxrc options between lines with '# {start,end}_linuxrc_conf'; - * otherwise the file content is ignored - */ - log_info("parsing AutoYaST file\n"); - file_read_info_file("file:/download/autoinst.xml", kf_cfg); - net_update_ifcfg(IFCFG_IFUP); - } - else { - log_show_maybe(!url->quiet, "Failed to download AutoYaST file.\n"); - } - } + auto2_read_autoyast(config.url.autoyast && config.autoyast_parse ? config.url.autoyast : config.url.autoyast2); /* load & run driverupdates */ if(config.update.urls) { @@ -863,6 +843,28 @@ return console; } +/* + * Read a single file from repo directory. + * + * Be careful not to replace an existing file unless we successfully got + * a new version. + */ +void auto2_read_repo_file(url_t *url, char *src, char *dst) +{ + char *tmp_file = NULL; + + str_copy(&tmp_file, new_download()); + if( + !url_read_file(url, NULL, src, tmp_file, NULL, URL_FLAG_NODIGEST + URL_FLAG_OPTIONAL) && + util_check_exist(tmp_file) + ) { + rename(tmp_file, dst); + log_info("mv %s -> %s\n", tmp_file, dst); + } + + str_copy(&tmp_file, NULL); +} + /* * Get various files from repositrory for yast's convenience. @@ -870,9 +872,7 @@ void auto2_read_repo_files(url_t *url) { int i; - char *tmp_file = NULL; static char *default_list[][2] = { - { "/autoinst.xml", "/tmp/autoinst.xml" }, { "/control.xml", "/control.xml" }, { "/license.tar.gz", "/license.tar.gz" }, { "/media.1/info.txt", "/info.txt" }, @@ -881,29 +881,37 @@ }; for(i = 0; i < sizeof default_list / sizeof *default_list; i++) { - // be careful not to replace an existing file unless we successfully got - // a new version - str_copy(&tmp_file, new_download()); + auto2_read_repo_file(url, default_list[i][0], default_list[i][1]); + } + + char *autoyast_file = NULL; + + if(config.url.autoyast) { if( - !url_read_file(url, NULL, default_list[i][0], tmp_file, NULL, URL_FLAG_NODIGEST + URL_FLAG_OPTIONAL) && - util_check_exist(tmp_file) + config.url.autoyast->scheme == inst_rel && + config.autoyast_parse ) { - rename(tmp_file, default_list[i][1]); - log_info("mv %s -> %s\n", tmp_file, default_list[i][1]); + log_show_maybe(!config.url.autoyast->quiet, "AutoYaST file in repo: %s\n", url_print(config.url.autoyast, 5)); + + if(!config.url.autoyast->is.dir) { + autoyast_file = config.url.autoyast->path; + } } } + else { + autoyast_file = "/autoinst.xml"; + } - str_copy(&tmp_file, NULL); + if(autoyast_file) { + auto2_read_repo_file(url, autoyast_file, "/tmp/autoinst.xml"); - if(!config.autoyast) { if(util_check_exist("/tmp/autoinst.xml")) rename("/tmp/autoinst.xml", "/autoinst.xml"); + if(util_check_exist("/autoinst.xml")) { - log_info("setting AutoYaST option to file:///autoinst.xml\n"); - str_copy(&config.autoyast, "file:///autoinst.xml"); - /* parse it: - * you can embed linuxrc options between lines with '# {start,end}_linuxrc_conf'; - * otherwise the file content is ignored - */ + log_info("setting AutoYaST option to file:/autoinst.xml\n"); + url_free(config.url.autoyast); + config.url.autoyast = url_set("file:/autoinst.xml"); + // parse for embedded linuxrc options in <info_file> element log_info("parsing AutoYaST file\n"); file_read_info_file("file:/autoinst.xml", kf_cfg); net_update_ifcfg(IFCFG_IFUP); @@ -920,31 +928,18 @@ void auto2_read_repomd_files(url_t *url) { int i; - char *tmp_file = NULL; static char *default_list[][2] = { { "license", "/license.tar.gz" }, { "/README.BETA", "/README.BETA" } }; for(i = 0; i < sizeof default_list / sizeof *default_list; i++) { - // be careful not to replace an existing file unless we successfully got - // a new version - // get real file name slist_t *sl = slist_getentry(config.repomd_data, default_list[i][0]); if(!sl) continue; - str_copy(&tmp_file, new_download()); - if( - !url_read_file(url, NULL, sl->value, tmp_file, NULL, URL_FLAG_NODIGEST) && - util_check_exist(tmp_file) - ) { - rename(tmp_file, default_list[i][1]); - log_info("mv %s -> %s\n", tmp_file, default_list[i][1]); - } + auto2_read_repo_file(url, sl->value, default_list[i][1]); } - - str_copy(&tmp_file, NULL); } @@ -1242,3 +1237,55 @@ return err; } + +/* + * Read autoyast file from url and parse it. + * + * If the autoyast url points to a directory, nothing is read but the + * function tries to mount the directory to ensure it exists. This is + * basically done to search for the correct medium. + */ +void auto2_read_autoyast(url_t *url) +{ + if(!url) return; + + // rel url is taken care of in auto2_read_repo_files() + if(url->scheme == inst_rel) return; + + /* + * If the AutoYaST url is a directory we have to very its existence + * somehow. + * + * That works for mountable url schemes. + * + * For the rest (http(s), (t)ftp) we'll just assume it works. + */ + if(url->is.dir) { + /* + * do nothing but + * - ensure network is set up + * - the correct disk device has been identified + */ + if(url->is.mountable) { + url_mount(url, NULL, NULL); + url_umount(url); + } + + return; + } + + log_show_maybe(!url->quiet, "Downloading AutoYaST file: %s\n", url->str); + + int err = url_read_file_anywhere(url, NULL, NULL, "/download/autoinst.xml", NULL, URL_FLAG_PROGRESS + URL_FLAG_NODIGEST); + url_umount(url); + + if(!err) { + // parse for embedded linuxrc options in <info_file> element + log_info("parsing AutoYaST file\n"); + file_read_info_file("file:/download/autoinst.xml", kf_cfg); + net_update_ifcfg(IFCFG_IFUP); + } + else { + log_show_maybe(!url->quiet, "Failed to download AutoYaST file.\n"); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/changelog new/linuxrc-7.0.0/changelog --- old/linuxrc-6.0.15/changelog 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/changelog 2019-10-23 15:46:25.000000000 +0200 @@ -1,3 +1,18 @@ +2019-10-23: 7.0.0 + - merge gh#openSUSE/linuxrc#196 + - show debug info also on console device + - fix reading slp data + - show both autoyast and autoyast2 options on linuxrc info page + - support autoyast-style URL syntax + - read and parse autoyast file + - add needed entries to global config struct + - add new autoyast.parse key + - parse autoyast/autoyast2 options and add new autoyast url schemes + - activate new autoyast code + - fix parsing linuxrc options embedded in AutoYaST file (bsc#1145574) + - document autoyast option behavior + - small additions to autoyast handling doc + 2019-09-24: 6.0.15 - merge gh#openSUSE/linuxrc#195 - add support for compressed modules diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/file.c new/linuxrc-7.0.0/file.c --- old/linuxrc-6.0.15/file.c 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/file.c 2019-10-23 15:46:25.000000000 +0200 @@ -117,6 +117,9 @@ { key_screenmap, "Screenmap", kf_none }, { key_fontmagic, "Fontmagic", kf_none }, { key_autoyast, "AutoYaST", kf_cfg + kf_cmd_early }, + { key_autoyast, "AY", kf_cfg + kf_cmd_early }, + { key_autoyast_parse, "AutoYaSTParse", kf_cfg + kf_cmd_early }, + { key_autoyast_parse, "AYParse", kf_cfg + kf_cmd_early }, { key_autoyast2, "AutoYaST2", kf_cfg + kf_cmd_early }, { key_linuxrc, "linuxrc", kf_cfg + kf_cmd_early }, { key_forceinsmod, "ForceInsmod", kf_cfg + kf_cmd }, @@ -350,11 +353,16 @@ { "exec", inst_exec }, { "rel", inst_rel }, { "disk", inst_disk }, - { "extern", inst_extern }, + { "usb", inst_usb }, + { "label", inst_label }, /* add new inst modes _here_! */ + { "extern", inst_extern }, + /* the following are just aliases */ { "harddisk", inst_hd }, { "cdrom", inst_cdrom }, { "cifs", inst_smb }, + { "device", inst_disk }, + { "relurl", inst_rel }, #if defined(__s390__) || defined(__s390x__) { "osa", di_390net_osa }, { "ctc", di_390net_ctc }, @@ -627,20 +635,29 @@ unsigned u; FILE *w; - /* maybe it's an AutoYaST XML file */ + /* + * Maybe it's an AutoYaST XML file. + * + * If so, try limiting the scope to lines in first '<info_file>' element. + */ for(f = f0; f; f = f->next) { - if(f->key == key_comment && !strcmp(f->value, "start_linuxrc_conf")) { - is_xml = 1; - f0 = f->next; - break; + if(f->key == key_none) { + if(!strncmp(f->key_str, "<info_file", sizeof "<info_file" - 1)) { + is_xml = 1; + f0 = f->next; + break; + } + if(!strcmp(f->key_str, "</profile>")) { + is_xml = 1; + } } } for(f = f0; f; f = f->next) { if( is_xml && - f->key == key_comment && - !strcmp(f->value, "end_linuxrc_conf") + f->key == key_none && + !strcmp(f->key_str, "</info_file>") ) { break; } @@ -843,12 +860,24 @@ break; case key_autoyast: - str_copy(&config.autoyast, *f->value ? f->value : "default"); + config.url.autoyast = url_free(config.url.autoyast); + if(strcmp(f->value, "default")) { + config.url.autoyast = url_set(f->value); + // if it's an SLP url, add 'autoyast' service query per default + if(config.url.autoyast->scheme == inst_slp) { + slist_setentry(&config.url.autoyast->query, "service", "autoyast", 0); + } + } config.manual = 0; break; case key_autoyast2: - str_copy(&config.autoyast2, *f->value ? f->value : NULL); + url_free(config.url.autoyast2); + config.url.autoyast2 = url_set(f->value); + break; + + case key_autoyast_parse: + if(f->is.numeric) config.autoyast_parse = f->nvalue; break; case key_info: @@ -1087,11 +1116,20 @@ } slist_free(sl0); + config.log.dest[1].level = + config.debug ? LOG_LEVEL_SHOW | LOG_LEVEL_INFO | LOG_LEVEL_DEBUG | LOG_TIMESTAMP : LOG_LEVEL_INFO; + if(config.error_trace) { config.log.dest[2].level |= LOG_CALLER; + if(config.debug) { + config.log.dest[1].level |= LOG_CALLER; + } } else { config.log.dest[2].level &= ~LOG_CALLER; + if(config.debug) { + config.log.dest[1].level &= ~LOG_CALLER; + } } break; @@ -1919,13 +1957,18 @@ file_write_str(f, key_updatedir, config.update.dir); file_write_num(f, key_yast2update, config.update.ask || config.update.count ? 1 : 0); file_write_num(f, key_textmode, config.textmode); - file_write_str(f, key_autoyast, config.autoyast); + if(config.url.autoyast) { + log_info("final autoyast url: %s\n", url_print(config.url.autoyast, 0)); + file_write_str(f, key_autoyast, + config.autoyast_parse ? url_print(config.url.autoyast, 5) : config.url.autoyast->str + ); + } /* * autoyast + upgrade = autoupgrade * * autoyast uses a different config var to trigger updates for historical reasons */ - if(config.autoyast && config.upgrade) { + if(config.url.autoyast && config.upgrade) { fprintf(f, "AutoUpgrade: 1\n"); } file_write_num(f, key_memfree, config.memoryXXX.current >> 10); // convention: in kB diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/file.h new/linuxrc-7.0.0/file.h --- old/linuxrc-6.0.15/file.h 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/file.h 2019-10-23 15:46:25.000000000 +0200 @@ -56,7 +56,7 @@ key_withipoib, key_upgrade, key_media_upgrade, key_ifcfg, key_defaultinstall, key_nanny, key_vlanid, key_sshkey, key_systemboot, key_sethostname, key_debugshell, key_self_update, - key_ibft_devices, key_linuxrc_core, key_norepo, key_auto_assembly + key_ibft_devices, key_linuxrc_core, key_norepo, key_auto_assembly, key_autoyast_parse } file_key_t; typedef enum { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/global.h new/linuxrc-7.0.0/global.h --- old/linuxrc-6.0.15/global.h 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/global.h 2019-10-23 15:46:25.000000000 +0200 @@ -185,7 +185,7 @@ inst_none = 0, inst_file, inst_nfs, inst_ftp, inst_smb, inst_http, inst_https, inst_tftp, inst_cdrom, inst_floppy, inst_hd, inst_dvd, inst_cdwithnet, inst_net, inst_slp, inst_exec, - inst_rel, inst_disk, + inst_rel, inst_disk, inst_usb, inst_label, inst_extern ///< must be last } instmode_t; @@ -265,6 +265,7 @@ typedef struct { char *str; instmode_t scheme; + instmode_t orig_scheme; char *server; char *share; char *path; @@ -287,6 +288,7 @@ unsigned mountable:1; /**< scheme is mountable */ unsigned cdrom:1; /**< device is cdrom */ unsigned file:1; /**< path points to file (not to directory) */ + unsigned dir:1; /**< path points to directory (not to file ) */ unsigned wlan:1; /**< wlan interface */ unsigned blockdev:1; /**< needs block device */ unsigned nodevneeded:1; /**< does not need any device */ @@ -446,6 +448,7 @@ unsigned repomd:1; /**< install repo is repo-md */ unsigned norepo:1; /**< disable repo location check, expect YaST */ unsigned auto_assembly:1; /**< enable MD/RAID auto-assembly */ + unsigned autoyast_parse:1; /**< analyse autoyast parameter */ struct { unsigned check:1; /**< check for braille displays and start brld if found */ char *dev; /**< braille device */ @@ -465,8 +468,6 @@ slist_t *file; /**< 'info' file name */ unsigned add_cmdline:1; /**< parse cmdline, too */ } info; - char *autoyast; /**< yast autoinstall parameter */ - char *autoyast2; /**< yast autoinstall parameter, loaded by linuxrc */ char *yepurl; /**< just pass it to yast */ char *supporturl; /**< just pass it to yast */ slist_t *linuxrc; /**< 'linuxrc' parameters */ @@ -540,6 +541,8 @@ url_t *install; /**< install url */ url_t *instsys; /**< instsys url */ url_t *proxy; /**< proxy url */ + url_t *autoyast; /**< yast autoinstall parameter */ + url_t *autoyast2; /**< alternative yast autoinstall parameter */ } url; struct { /**< libblkid related things */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/linuxrc.c new/linuxrc-7.0.0/linuxrc.c --- old/linuxrc-6.0.15/linuxrc.c 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/linuxrc.c 2019-10-23 15:46:25.000000000 +0200 @@ -801,6 +801,7 @@ config.devtmpfs = 1; config.kexec = 2; /* kexec if necessary, with user dialog */ config.auto_assembly = 0; /* default to disable MD/RAID auto-assembly (bsc#1132688) */ + config.autoyast_parse = 1; /* analyse autoyast option and read autoyast file */ // defaults for self-update feature config.self_update_url = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/linuxrc_and_autoyast.md new/linuxrc-7.0.0/linuxrc_and_autoyast.md --- old/linuxrc-6.0.15/linuxrc_and_autoyast.md 1970-01-01 01:00:00.000000000 +0100 +++ new/linuxrc-7.0.0/linuxrc_and_autoyast.md 2019-10-23 15:46:25.000000000 +0200 @@ -0,0 +1,78 @@ +# AutoYaST handling in linuxrc + +## Why? + +AutoYaST is something very specific to YaST and linuxrc has nothing to do +with it. So why would it have to deal with it at all? + +In fact, linuxrc did ignore the `autoyast` boot option for a long time and +just passed it on via `/etc/install.inf` to yast. + +There are several reasons why linuxrc has to get involved: + +1. You can embed linuxrc options into the AutoYaST config + https://doc.opensuse.org/projects/autoyast/#invoking_autoinst.linuxrc. + +2. An AutoYaST config file `/autoinst.xml` is searched for and auto-loaded from a disk with label `OEMDRV`. + +3. There is the expectation that using `autoyast=ftp://foo/bar` (or any network URL) causes linuxrc + to implicitly set up the network; much like `install=URL` or`dud=URL` does. + +For 3. to work linuxrc has to download the AutoYaST file to be sure the +network setup has been done correctly. + +For 2. (and partly 1.) there had been the `autoyast2` option. But that was +limited to linuxrc-style URLs and did not make any attempt to deal with +AutoYaST rules. + +The main obstacles so far to get it right were: + +- AutoYaST has its own idiosyncratic set of URL schemes +- it's not obvious which file should actually be loaded when AutoYaST rules come into play + +## Implementation + +1. linuxrc supports all AutoYaST URL schemes (see [References](#references) below); this +implies you can also use AutoYaST-style URLs in other places in linuxrc +2. linuxrc downloads the AutoYaST config file and parses it for linuxrc options - unless it's +a rules-based setup +3. linuxrc converts the URL used with the `autoyast` option into the canonical AutoYaST format and +passes this on via `/etc/install.inf`; this means you can use both linuxrc-style and AutoYaST-style URLs +in linuxrc +4. if the AutoYaST URL ends with a `/` (pointing to a directory) linuxrc +assumes this to be a rules-based setup; for URLs with a mountable scheme, +linuxrc goes looking for the specified directory; for all other URL schemes +linuxrc does nothing and simply passes the URL on to YaST +5. for URL schemes `usb` and `label` linuxrc identifies the device and converts the URL to a `device` scheme +to ensure AutoYaST reads the same config; but if linuxrc could not find the AutoYaST file at +the specified location, the original URL is passed +6. for the `slp` scheme, linuxrc does the URL query and offers the user a +selection dialog; the selected URL is then passed on to YaST; this makes the +`slp` scheme work as documented (with `descr=XXX` query parameter) - which +so far did not work +7. linuxrc implicitly looks for an AutoYaST config file `autoinst.xml` in the repository directory; the +file is downloaded as `/autoinst.xml` and a link to it passed on to YaST (using a `file` URL) +8. there is not really an `autoyast=default` option; if this option is used, it just clears any previous +autoyast setting; the reason is that `autoyast=default` is the default - linuxrc **always** looks for +an AutoYaST config in the repository as described in 7.; see also +https://en.opensuse.org/SDB:Linuxrc#AutoYaST_Profile_Handling +9. as this is a major change and issues are likely to show up, there is a boot option to get back +the old behavior: `autoyast.parse=0` - with this the `autoyast` option is left alone and just passed +on to YaST +10. the `autoyast2` option still exists for compatibility; it is ignored when `autoyast` is used +11. there's a short alias `ay` for the `autoyast` option + +## References + +AutoYaST URL scheme doc + +- https://doc.opensuse.org/projects/autoyast/#Commandline.ay + +Understanding AutoYaST rules handling + +- https://doc.opensuse.org/projects/autoyast/#handlingrules + +Implementation of AutoYaST config file reading in YaST + +- https://github.com/yast/yast-installation/blob/master/src/lib/transfer/file_from_url.rb +- https://github.com/yast/yast-autoinstallation/blob/master/src/modules/AutoinstConfig.rb diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/slp.c new/linuxrc-7.0.0/slp.c --- old/linuxrc-6.0.15/slp.c 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/slp.c 2019-10-23 15:46:25.000000000 +0200 @@ -112,8 +112,8 @@ int s, l, l2, l3; int xid, al; char *d; - unsigned char sendbuf[8000]; - unsigned char recvbuf[8000]; + unsigned char sendbuf[0x10000]; + unsigned char recvbuf[0x10000]; unsigned char *bp, *end; xid = nextxid; @@ -184,8 +184,8 @@ char *slp_get_install(url_t *url) { - unsigned char sendbuf[8000]; - unsigned char recvbuf[80000]; + unsigned char sendbuf[0x100000]; + unsigned char recvbuf[0x100000]; unsigned char *bp, *end, *service, service_key[256]; int xid, l, s, l2, l3, ec, comma, ulen, i, acnt, service_key_len; struct sockaddr_in mysa; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/url.c new/linuxrc-7.0.0/url.c --- old/linuxrc-6.0.15/url.c 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/url.c 2019-10-23 15:46:25.000000000 +0200 @@ -60,6 +60,11 @@ static int url_setup_device(url_t *url); static int url_setup_interface(url_t *url); static int url_setup_slp(url_t *url); +static void fixup_url_rel(url_t *url); +static void fixup_url_usb(url_t *url); +static void fixup_url_label(url_t *url); +static void skip_slashes(char **str); +static void skip_not_slashes(char **str); static void url_parse_instsys_config(char *file); static slist_t *url_instsys_lookup(char *key, slist_t **sl_ll); static char *url_instsys_config(char *path); @@ -73,6 +78,7 @@ static hd_t *sort_a_bit(hd_t *hd_list); static int link_detected(hd_t *hd); static char *url_print_zypp(url_t *url); +static char *url_print_autoyast(url_t *url); static void digests_init(url_data_t *url_data); static void digests_done(url_data_t *url_data); static void digests_process(url_data_t *url_data, void *buffer, size_t len); @@ -347,12 +353,36 @@ /* - * scheme://domain;user:password@server:port/path?query + * Parse URL string. + * + * Return a freshly allocated url_t structure. + * + * A URL looks like: scheme://domain;user:password@server:port/path?query. * - * cifs: path = share/path - * disk: path = [device/]path + * For a general URL syntax overview, see + * - https://tools.ietf.org/html/rfc3986#section-3 + * - https://tools.ietf.org/html/rfc1738 (older, with more examples) + * + * Notes: + * - 'path' is prefixed with the share name ('share/path') for SMB/CIFS + * - 'path' may optionally be prefixed with the device name ('device/path') + * for URLs referring to local block devices + * - 'domain' (aka workgroup) and 'share' are only relevant for SMB/CIFS + * + * Special AutoYaST URL schemes (note the *two* slashes ('//'): + * - device://dev/path + * -> is mapped to disk:/path?device=dev + * - relurl://path + * -> is mapped to rel:path + * - usb://path + * -> is mapped to disk:/path?device=disk/\*usb* + * - label://label/path + * -> is mapped to disk:/path?device=disk/by-label/label + * + * Additionally, zero up to three consecutive slashes are acceptable at + * the beginning of the URL as long as the meaning is unambiguous (e.g. + * 'label:foo'). */ - url_t *url_set(char *str) { url_t *url = calloc(1, sizeof *url); @@ -400,13 +430,12 @@ } } else { - // FIXME: should always be 'rel' - i = file_sym2num(str); - if(i >= 0) { + i = url_scheme2id(str); + if(i > 0) { url->scheme = i; url->path = strdup(""); } - else if(i == -1) { + else { url->scheme = inst_rel; url->path = strdup(str); } @@ -485,6 +514,15 @@ } } + url->orig_scheme = url->scheme; + + /* adjust some url schemes to support autoyast syntax */ + fixup_url_rel(url); + fixup_url_usb(url); + fixup_url_label(url); + + url->is.blockdev = url_is_blockdev(url->scheme); + /* local storage device: allow path to begin with device name */ if( url->is.blockdev && @@ -535,6 +573,7 @@ if((sl = slist_getentry(url->query, "type"))) { url->is.file = strcmp(sl->value, "file") ? 0 : 1; + url->is.dir = strcmp(sl->value, "dir") ? 0 : 1; } if((sl = slist_getentry(url->query, "all"))) { @@ -547,8 +586,6 @@ url->is.mountable = url_is_mountable(url->scheme); - url->is.blockdev = url_is_blockdev(url->scheme); - url->is.network = url_is_network(url->scheme); url->is.nodevneeded = !(url->is.network || url->is.blockdev); @@ -572,10 +609,21 @@ } } + /* if URL path ends with '/', assume directory */ + if(!url->is.file) { + if(url->path && *url->path && url->path[strlen(url->path) - 1] == '/') { + url->is.dir = 1; + } + } + log_debug("url = %s\n", url->str); if(config.debug >= 2) { - log_debug(" scheme = %s (%d)", url_scheme2name(url->scheme), url->scheme); + log_debug( + " scheme = %s (%d), orig scheme = %s (%d)", + url_scheme2name(url->scheme), url->scheme, + url_scheme2name(url->orig_scheme), url->orig_scheme + ); if(url->server) log_debug(", server = \"%s\"", url->server); if(url->port) log_debug(", port = %u", url->port); if(url->path) log_debug(", path = \"%s\"", url->path); @@ -597,8 +645,8 @@ } log_debug( - " network = %u, blockdev = %u, mountable = %u, file = %u, all = %u, quiet = %u\n", - url->is.network, url->is.blockdev, url->is.mountable, url->is.file, + " network = %u, blockdev = %u, mountable = %u, file = %u, dir = %u, all = %u, quiet = %u\n", + url->is.network, url->is.blockdev, url->is.mountable, url->is.file, url->is.dir, url->search_all, url->quiet ); @@ -610,6 +658,9 @@ log_debug(" %s = \"%s\"\n", sl->key, sl->value); } } + + log_debug("url (zypp format) = %s\n", url_print(url, 4)); + log_debug("url (ay format) = %s\n", url_print(url, 5)); } return url; @@ -617,6 +668,119 @@ /* + * Fix up autoyast 'rel' url scheme. + * + * - relurl://foo/bar + * + * Note the '//'. + */ +void fixup_url_rel(url_t *url) +{ + if( + url->scheme == inst_rel && + url->server && + url->path + ) { + if(!*url->path) { + free(url->path); + url->path = url->server; + url->server = NULL; + } + else { + strprintf(&url->path, "%s/%s", url->server, url->path); + str_copy(&url->server, NULL); + } + } +} + + +/* + * Fix up autoyast 'usb' url scheme. + * + * - usb://foo/bar + * + * Note the '//'. + * + * 'usb' is translated to the 'disk' url scheme with a suitable '?device=XXX' + * query parameter added to take care of matching only usb devices. + */ +void fixup_url_usb(url_t *url) +{ + if(url->scheme != inst_usb) return; + + url->scheme = inst_disk; + slist_setentry(&url->query, "device", "disk/*usb*", 1); + + if(url->server && url->path) { + if(!*url->path) { + free(url->path); + url->path = url->server; + url->server = NULL; + } + else { + strprintf(&url->path, "%s/%s", url->server, url->path); + str_copy(&url->server, NULL); + } + } +} + + +/* + * Handle autoyast 'label' scheme. + * + * - label://label/foo/bar + * + * 'label' is translated to the 'disk' url scheme with a suitable '?device=XXX' + * query parameter added to take care of matching the label. + */ +void fixup_url_label(url_t *url) +{ + if(url->scheme != inst_label) return; + + url->scheme = inst_disk; + + if(url->server) { + slist_t *sl = slist_setentry(&url->query, "device", NULL, 1); + strprintf(&sl->value, "disk/by-label/%s", url->server); + slist_setentry(&url->query, "label", url->server, 1); + } + else if(url->path) { + char *s = url->path; + skip_slashes(&s); + if(*s) { + char *t = s; + skip_not_slashes(&t); + if(t != s) { + if(*t) *t++ = 0; + slist_t *sl = slist_setentry(&url->query, "device", NULL, 1); + strprintf(&sl->value, "disk/by-label/%s", s); + slist_setentry(&url->query, "label", s, 1); + str_copy(&url->path, t); + } + } + } +} + + +/* + * Skip sequence of slashes ('/'). + */ +void skip_slashes(char **str) +{ + while(**str && **str == '/') (*str)++; +} + + +/* + * Skip sequence of non-slashes (not '/'). + */ +void skip_not_slashes(char **str) +{ + while(**str && **str != '/') (*str)++; +} + + +/* * Print url to string. * * scheme://domain;user:password@server:port/path?query @@ -627,6 +791,7 @@ * 2: with device * 3: like 2, but remove 'rel:' scheme * 4: in zypp format + * 5: in autoyast format */ char *url_print(url_t *url, int format) { @@ -642,6 +807,8 @@ if(format == 4) return url_print_zypp(url); + if(format == 5) return url_print_autoyast(url); + if(format != 3 || url->scheme != inst_rel) { strprintf(&buf, "%s:", url_scheme2name(url->scheme)); } @@ -694,6 +861,14 @@ } if(format == 0) { + // basically for the slp scheme + static char *params[] = { "service", "descr" }; + slist_t *sl; + for (int i = 0; i < sizeof params / sizeof *params; i++) { + if((sl = slist_getentry(url->query, params[i]))) { + strprintf(&buf, "%s%c%s=%s", buf, q++ ? '&' : '?', sl->key, sl->value); + } + } if(config.debug >= 2 && url->used.hwaddr) { strprintf(&buf, "%s%chwaddr=%s", buf, q++ ? '&' : '?', url->used.hwaddr); } @@ -835,6 +1010,107 @@ } +/* + * Convert URL to AutoYAST format. + * + * url scheme doc + * - https://doc.opensuse.org/projects/autoyast/#Commandline.ay + * + * actual implementation + * - https://github.com/yast/yast-installation/blob/master/src/lib/transfer/file_from_url.rb + * - https://github.com/yast/yast-autoinstallation/blob/master/src/modules/AutoinstConfig.rb + */ +char *url_print_autoyast(url_t *url) +{ + static char *buf = NULL, *s; + char *path = NULL, *file = NULL; + int scheme; + + str_copy(&buf, NULL); + + str_copy(&path, url->path); + + if(url->is.file && path) { + if((file = strrchr(path, '/')) && *file) { + *file++ = 0; + } + else { + file = NULL; + } + } + + scheme = url->scheme; + + if(url->is.blockdev) { + strprintf(&buf, "device://"); + if(url->used.device) { + strprintf(&buf, "%s%s", buf, short_dev(url->used.device)); + } + else if(url->orig_scheme == inst_usb) { + strprintf(&buf, "usb:/"); + } + else if(url->orig_scheme == inst_label) { + slist_t *sl; + strprintf(&buf, "label://"); + if((sl = slist_getentry(url->query, "label"))) { + strprintf(&buf, "%s%s", buf, sl->value); + } + } + } + else if(scheme == inst_rel) { + strprintf(&buf, "relurl:/"); + } + else if(scheme == inst_file) { + strprintf(&buf, "file://"); + } + else if(scheme == inst_slp) { + strprintf(&buf, "slp"); + } + else { + strprintf(&buf, "%s:", url_scheme2name(scheme)); + } + + if(url->domain || url->user || url->password || url->server || url->port) { + strprintf(&buf, "%s//", buf); + if(url->domain) strprintf(&buf, "%s%s;", buf, url->domain); + if(url->user) { + s = curl_easy_escape(NULL, url->user, 0); + strprintf(&buf, "%s%s", buf, s); + curl_free(s); + } + if(url->password) { + s = curl_easy_escape(NULL, url->password, 0); + strprintf(&buf, "%s:%s", buf, s); + curl_free(s); + } + if(url->user || url->password) strprintf(&buf, "%s@", buf); + if(url->server) { + if(strchr(url->server, ':')) { + strprintf(&buf, "%s[%s]", buf, url->server); + } + else { + strprintf(&buf, "%s%s", buf, url->server); + } + } + if(url->port) strprintf(&buf, "%s:%u", buf, url->port); + } + + if(url->share) strprintf(&buf, "%s/%s", buf, url->share); + + if(path && url->scheme != inst_slp) { + strprintf(&buf, "%s/%s%s", + buf, + url->scheme == inst_ftp && *path == '/' ? "%2F" : "", + *path == '/' ? path + 1 : path + ); + } + + str_copy(&path, NULL); + + return buf; +} + + char *url_print2(url_t *url, char *file) { static char *buf = NULL, *s = ""; @@ -3425,7 +3701,11 @@ i = file_sym2num(scheme); - if(i >= 0) return i; + if(i >= 0) { + char *str = url_scheme2name(i); + // ensure it really matches the expected scheme + if(str && !strcmp(str, scheme)) return i; + } if(util_check_exist2("/scripts/url", scheme) == 'd') { char *attr = NULL, *attr_val; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-6.0.15/util.c new/linuxrc-7.0.0/util.c --- old/linuxrc-6.0.15/util.c 2019-09-24 15:39:06.000000000 +0200 +++ new/linuxrc-7.0.0/util.c 2019-10-23 15:46:25.000000000 +0200 @@ -1247,8 +1247,15 @@ slist_append_str(&sl0, buf); } - if(config.autoyast) { - sprintf(buf, "autoyast = %s", config.autoyast); + if((s = url_print(config.url.autoyast, 0))) { + slist_append_str(&sl0, "autoyast url:"); + sprintf(buf, " %s", s); + slist_append_str(&sl0, buf); + } + + if((s = url_print(config.url.autoyast2, 0))) { + slist_append_str(&sl0, "autoyast2 url:"); + sprintf(buf, " %s", s); slist_append_str(&sl0, buf); }