Hello community,

here is the log from the commit of package linuxrc for openSUSE:Factory checked 
in at 2016-02-23 16:53:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/linuxrc (Old)
 and      /work/SRC/openSUSE:Factory/.linuxrc.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "linuxrc"

Changes:
--------
--- /work/SRC/openSUSE:Factory/linuxrc/linuxrc.changes  2016-02-17 
12:15:15.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.linuxrc.new/linuxrc.changes     2016-02-23 
16:53:02.000000000 +0100
@@ -1,0 +2,14 @@
+Thu Feb 18 10:20:17 UTC 2016 - [email protected]
+
+- fix extension handling
+- improve user-defined url doc (fate#318899)
+- handle empty path component in url
+- user-defined urls: add linuxrc menus for network urls
+- user-defined urls: add linuxrc menus for local urls
+- add doc for user-defined urls
+- implement user-defined mountable url schemes
+- consolidate handling of url properties
+- introduce externally handled URL schemes
+- 5.0.72
+
+-------------------------------------------------------------------

Old:
----
  linuxrc-5.0.71.tar.xz

New:
----
  linuxrc-5.0.72.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ linuxrc.spec ++++++
--- /var/tmp/diff_new_pack.1ZS5GX/_old  2016-02-23 16:53:03.000000000 +0100
+++ /var/tmp/diff_new_pack.1ZS5GX/_new  2016-02-23 16:53:03.000000000 +0100
@@ -25,7 +25,7 @@
 Summary:        SUSE Installation Program
 License:        GPL-3.0+
 Group:          System/Boot
-Version:        5.0.71
+Version:        5.0.72
 Release:        0
 Source:         %{name}-%{version}.tar.xz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build

++++++ linuxrc-5.0.71.tar.xz -> linuxrc-5.0.72.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/VERSION new/linuxrc-5.0.72/VERSION
--- old/linuxrc-5.0.71/VERSION  2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/VERSION  2016-02-18 11:18:29.000000000 +0100
@@ -1 +1 @@
-5.0.71
+5.0.72
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/auto2.c new/linuxrc-5.0.72/auto2.c
--- old/linuxrc-5.0.71/auto2.c  2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/auto2.c  2016-02-18 11:18:29.000000000 +0100
@@ -514,7 +514,7 @@
 
   log_debug("test_and_add_dud: all = %u\n", url->search_all);
 
-  is_dud = util_chk_driver_update(config.mountpoint.update, 
get_instmode_name(url->scheme));
+  is_dud = util_chk_driver_update(config.mountpoint.update, 
url_scheme2name(url->scheme));
 
   LXRC_WAIT;
 
@@ -1032,7 +1032,7 @@
 
   if(!err) err = util_mount_ro(file_name, config.mountpoint.update, NULL);
 
-  if(!err) util_chk_driver_update(config.mountpoint.update, 
get_instmode_name(url->scheme));
+  if(!err) util_chk_driver_update(config.mountpoint.update, 
url_scheme2name(url->scheme));
 
   util_umount(config.mountpoint.update);
 
@@ -1042,7 +1042,7 @@
 
   /* then, look for unpacked version */
   if(url->mount) {
-    util_chk_driver_update(url->mount, get_instmode_name(url->scheme));
+    util_chk_driver_update(url->mount, url_scheme2name(url->scheme));
   }
 
   if(config.win) win_close(&win);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/changelog new/linuxrc-5.0.72/changelog
--- old/linuxrc-5.0.71/changelog        2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/changelog        2016-02-18 11:18:29.000000000 +0100
@@ -1,3 +1,14 @@
+2016-02-17:    5.0.72
+       - fix extension handling
+       - improve user-defined url doc (fate #318899)
+       - handle empty path component in url
+       - user-defined urls: add linuxrc menus for network urls
+       - user-defined urls: add linuxrc menus for local urls
+       - add doc for user-defined urls
+       - implement user-defined mountable url schemes
+       - consolidate handling of url properties
+       - introduce externally handled URL schemes
+
 2016-02-11:    5.0.71
        - Workaround O_TMPFILE definition on SLE12 / aarch64 (bsc #965068)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/dialog.c new/linuxrc-5.0.72/dialog.c
--- old/linuxrc-5.0.71/dialog.c 2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/dialog.c 2016-02-18 11:18:29.000000000 +0100
@@ -118,7 +118,6 @@
   { di_wlan_open,        "No Authentication"   },
   { di_wlan_wpa_psk,     "WPA-PSK"             },
   { di_wlan_wpa_peap,    "WPA-PEAP"            },
-
 };
 
 
@@ -1541,15 +1540,29 @@
 }
 
 
+/*
+ * Return menu text for item di.
+ */
 char *dia_get_text(dia_item_t di)
 {
   int i;
+  slist_t *sl;
   char *s = "";
 
-  for(i = 0; (unsigned) i < sizeof dia_texts / sizeof *dia_texts; i++) {
-    if(dia_texts[i].item == di) {
-      s = dia_texts[i].text;
-      break;
+  if(di >= di_extra) {
+    for(sl = config.dia_extra_texts, i = di_extra; sl; sl = sl->next, i++) {
+      if(i == di) {
+        s = sl->value;
+        break;
+      }
+    }
+  }
+  else {
+    for(i = 0; i < sizeof dia_texts / sizeof *dia_texts; i++) {
+      if(dia_texts[i].item == di) {
+        s = dia_texts[i].text;
+        break;
+      }
     }
   }
 
@@ -1557,6 +1570,47 @@
 }
 
 
+/*
+ * Return menu label for item di.
+ */
+char *dia_get_label(dia_item_t di)
+{
+  int i;
+  slist_t *sl;
+
+  if(di < di_extra) return NULL;
+
+  for(sl = config.dia_extra_texts, i = di_extra; sl; sl = sl->next, i++) {
+    if(i == di) return sl->key;
+  }
+
+  return NULL;
+}
+
+
+/*
+ * Get an id for menu entry.
+ *
+ * The returned id can later be used in dia_get_text() and dia_get_label()
+ * to get back text and label.
+ */
+dia_item_t dia_get_id(char *label, char *text)
+{
+  int i;
+  slist_t *sl;
+
+  if(!label || !text) return di_none;
+
+  for(sl = config.dia_extra_texts, i = di_extra; sl; sl = sl->next, i++) {
+    if(!strcmp(sl->key, label)) return i;
+  }
+
+  slist_setentry(&config.dia_extra_texts, label, text, 0);
+
+  return dia_get_id(label, text);
+}
+
+
 /*
  * returns selected menu item, or di_none (ESC pressed)
  */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/dialog.h new/linuxrc-5.0.72/dialog.h
--- old/linuxrc-5.0.71/dialog.h 2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/dialog.h 2016-02-18 11:18:29.000000000 +0100
@@ -102,6 +102,11 @@
   di_wlan_wpa_psk,
   di_wlan_wpa_peap,
 
+  /*
+   * must be last - placeholder for dynamically defined values
+   * cf. config.dia_extra_texts, dia_get_text_id()
+   */
+  di_extra
 } dia_item_t;
 
 typedef enum {
@@ -127,6 +132,8 @@
 
 int dia_message2(char *txt, int type);
 char *dia_get_text(dia_item_t di);
+char *dia_get_label(dia_item_t di);
+dia_item_t dia_get_id(char *label, char *text);
 dia_item_t dia_menu2(char *title, int width, int (*func)(dia_item_t), 
dia_item_t *items, dia_item_t default_item);
 int dia_list(char *title, int width, int (*func)(int), char **items, int 
default_item, dia_align_t align);
 int dia_show_lines2(char *head, slist_t *sl0, int width);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/file.c new/linuxrc-5.0.72/file.c
--- old/linuxrc-5.0.71/file.c   2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/file.c   2016-02-18 11:18:29.000000000 +0100
@@ -345,6 +345,7 @@
   { "exec",      inst_exec          },
   { "rel",       inst_rel           },
   { "disk",      inst_disk          },
+  { "extern",    inst_extern        },
   /* add new inst modes _here_! */
   { "harddisk",  inst_hd            },
   { "cdrom",     inst_cdrom         },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/global.h new/linuxrc-5.0.72/global.h
--- old/linuxrc-5.0.71/global.h 2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/global.h 2016-02-18 11:18:29.000000000 +0100
@@ -187,7 +187,8 @@
   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_extern // must be last
 } instmode_t;
 
 
@@ -275,6 +276,7 @@
   char *instsys;
   char *mount;
   char *tmp_mount;
+  char *rewrite_for_zypp;      /* pass this value instead of the original url 
to zypp */
   unsigned port;
   slist_t *query;
   slist_t *file_list;
@@ -287,6 +289,8 @@
     unsigned cdrom:1;          /* device is cdrom */
     unsigned file:1;           /* path points to file (not to directory) */
     unsigned wlan:1;           /* wlan interface */
+    unsigned blockdev:1;       /* needs block device */
+    unsigned nodevneeded:1;    /* does not need any device */
   } is;
   struct {
     char *device;
@@ -439,6 +443,7 @@
   unsigned nanny_set:1;                /* nanny setting was changed */
   unsigned upgrade:1;          /* upgrade or fresh install */
   unsigned systemboot:1;       /* boot installed system */
+  unsigned extend_running:1;   /* currently running an 'extend' job */
   struct {
     unsigned check:1;          /* check for braille displays and start brld if 
found */
     char *dev;                 /* braille device */
@@ -507,6 +512,8 @@
   char *run_command;           /* for 'run command' input field */
   slist_t *defaultrepo;                /* default repo locations */
   char *debugshell;            /* command to run if we want to start a shell 
for debugging */
+  slist_t *extern_scheme;      /* externally handled URL schemes */
+  slist_t *dia_extra_texts;    /* dynamically defined dialog entries; cf. 
dia_get_text_id() */
 
   struct {
     unsigned md5:1;            /* support md5 */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/install.c new/linuxrc-5.0.72/install.c
--- old/linuxrc-5.0.71/install.c        2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/install.c        2016-02-18 11:18:29.000000000 +0100
@@ -50,9 +50,18 @@
 #define MNT_DETACH     (1 << 1)
 #endif
 
+// maximum number of entries you can get in a dialog
+// - this is just more than you can reasonably expect -
+#define MAX_DIALOG_ITEMS       64
+
+// flags for inst_choose_partition()
+#define ICP_SWAP       1
+#define ICP_BLOCK_ALL  2
+
 static int inst_do_cdrom(void);
 static int inst_do_harddisk(void);
-int inst_do_network(instmode_t scheme);
+static int inst_do_mountable(instmode_t scheme);
+static int inst_do_network(instmode_t scheme);
 static int   add_instsys              (void);
 static void  inst_yast_done           (void);
 static int   inst_execute_yast        (void);
@@ -170,18 +179,27 @@
  */
 int inst_choose_netsource()
 {
+  int i, j;
+  slist_t *sl;
   dia_item_t di;
-  dia_item_t items[] = {
+  dia_item_t items[MAX_DIALOG_ITEMS] = {
     di_netsource_ftp,
     di_netsource_http,
     di_netsource_https,
     di_netsource_nfs,
     di_netsource_smb,
     di_netsource_tftp,
-    di_none
   };
 
-  if(!(config.test || config.net.cifs.binary)) items[3] = di_skip;
+ j = 6;        // first 6 items have aleady been filled in
+  for(sl = config.extern_scheme, i = inst_extern; sl; sl = sl->next, i++) {
+    if(sl->value && url_is_network(i)) {
+      items[j] = dia_get_id(sl->key, sl->value);
+      if(++j >= MAX_DIALOG_ITEMS - 1) break;
+    }
+  }
+
+  items[j] = di_none;
 
   if(di_inst_choose_netsource_last == di_none && config.url.install) {
     switch(config.url.install->scheme) {
@@ -226,6 +244,8 @@
 int inst_choose_netsource_cb(dia_item_t di)
 {
   int err = 0;
+  instmode_t scheme;
+  char *s;
 
   di_inst_choose_netsource_last = di;
 
@@ -255,6 +275,14 @@
       break;
 
     default:
+      s = dia_get_label(di);
+      if(s) {
+        scheme = url_scheme2id(s);
+        err = inst_do_network(scheme);
+      }
+      else {
+        err = 1;
+      }
       break;
   }
 
@@ -335,14 +363,25 @@
  */
 int inst_choose_source()
 {
+  int i, j;
+  slist_t *sl;
   dia_item_t di;
-  dia_item_t items[] = {
+  dia_item_t items[MAX_DIALOG_ITEMS] = {
     di_source_cdrom,
     di_source_net,
-    di_source_hd,
-    di_none
+    di_source_hd
   };
 
+  j = 3;       // first 3 items have aleady been filled in
+  for(sl = config.extern_scheme, i = inst_extern; sl; sl = sl->next, i++) {
+    if(sl->value && url_is_mountable(i) && !url_is_network(i)) {
+      items[j] = dia_get_id(sl->key, sl->value);
+      if(++j >= MAX_DIALOG_ITEMS - 1) break;
+    }
+  }
+
+  items[j] = di_none;
+
   if(di_inst_choose_source_last == di_none) {
     di_inst_choose_source_last = di_source_cdrom;
     if(config.url.install) {
@@ -372,6 +411,8 @@
 int inst_choose_source_cb(dia_item_t di)
 {
   int err = 0, rc = 0;
+  instmode_t scheme;
+  char *s;
 
   di_inst_choose_source_last = di;
 
@@ -389,6 +430,14 @@
       break;
 
     default:
+      s = dia_get_label(di);
+      if(s) {
+        scheme = url_scheme2id(s);
+        err = inst_do_mountable(scheme);
+      }
+      else {
+        err = 1;
+      }
       break;
   }
 
@@ -403,8 +452,13 @@
 
 /*
  * build a partition list
+ *
+ * flags:
+ *   0:             list all partitions with file systems on it
+ *   ICP_BLOCK_ALL: list all block devices + partitions (empty or used)
+ *   ICP_SWAP:      present selection for suitable swap partitions
  */
-int inst_choose_partition(char **partition, int swap, char *txt_menu, char 
*txt_input)
+int inst_choose_partition(char **partition, int flags, char *txt_menu, char 
*txt_input)
 {
   int i, j, rc, item_cnt, item_cnt1, item_cnt2, item_cnt3;
   char **items, **values;
@@ -419,11 +473,28 @@
   static char *last_part = NULL;
   int last_item, last_found, last_item1 = 0, last_item2 = 0, last_item3 = 0;
   char *module;
+  slist_t *device_list = NULL;
 
   util_update_disk_list(NULL, 1);
   util_update_swap_list();
 
-  for(i = 0, sl = config.partitions; sl; sl = sl->next) i++;
+  if((flags & ICP_BLOCK_ALL)) {
+    util_update_cdrom_list();
+
+    for(sl = config.cdroms; sl; sl = sl->next) {
+      slist_append_str(&device_list, sl->key);
+    }
+
+    for(sl = config.disks; sl; sl = sl->next) {
+      slist_append_str(&device_list, sl->key);
+    }
+  }
+
+  for(sl = config.partitions; sl; sl = sl->next) {
+    slist_append_str(&device_list, sl->key);
+  }
+
+  for(i = 0, sl = device_list; sl; sl = sl->next) i++;
 
   /*
    * Just max values, actual lists might be shorter.
@@ -436,7 +507,7 @@
   items3 = calloc(i + 4, sizeof *items3);
   values3 = calloc(i + 4, sizeof *values3);
 
-  for(item_cnt1 = item_cnt2 = item_cnt3 = 0, sl = config.partitions; sl; sl = 
sl->next) {
+  for(item_cnt1 = item_cnt2 = item_cnt3 = 0, sl = device_list; sl; sl = 
sl->next) {
     if(
       sl->key && !slist_getentry(config.swaps, sl->key)                /* 
don't show active swaps */
     ) {
@@ -454,7 +525,7 @@
         items1[item_cnt1++] = strdup(buf);
         if(last_found) last_item1 = item_cnt1;
       }
-      else if(type || swap) {
+      else if(type || (flags & (ICP_SWAP | ICP_BLOCK_ALL))) {
         values2[item_cnt2] = strdup(sl->key);
         items2[item_cnt2++] = strdup(buf);
         if(last_found) last_item2 = item_cnt2;
@@ -473,7 +544,7 @@
     items2[item_cnt2++] = strdup(buf);
   }
 
-  if(swap) {
+  if((flags & ICP_SWAP)) {
     values1[item_cnt1] = NULL;
     items1[item_cnt1++] = strdup("create swap partition");
     item_mk_part = item_cnt1;
@@ -484,12 +555,18 @@
     }
   }
 
-  if(swap) {
+  if((flags & ICP_SWAP)) {
     item_cnt = item_cnt1;
     items = items1;
     values = values1;
     last_item = last_item1;
   }
+  else if((flags & ICP_BLOCK_ALL)) {
+    item_cnt = item_cnt2;
+    items = items2;
+    values = values2;
+    last_item = last_item2;
+  }
   else {
     item_cnt = item_cnt3;
     items = items3;
@@ -509,100 +586,102 @@
       rc = 0;
     }
 
-    if(i == item_mk_part) {
-      do {
-        i = dia_list("create a swap partition", 36, NULL, items2, last_item2, 
align_left);
-        if(i > 0 && values2[i - 1]) {
-          str_copy(&last_part, values2[i - 1]);
-          dev = long_dev(values2[i - 1]);
-          sprintf(buf, "Warning: all data on %s will be deleted!", dev);
-          j = dia_contabort(buf, NO);
-          if(j == YES) {
-            sprintf(buf, "/sbin/mkswap %s", dev);
-            if(!lxrc_run(buf)) {
-              log_info("swapon %s\n", dev);
-              if(swapon(dev, 0)) {
-                log_info("swapon: ");
-                perror_info(dev);
-                dia_message("Error activating swap space.", MSGTYPE_ERROR);
+    if((flags & ICP_SWAP)) {
+      if(i == item_mk_part) {
+        do {
+          i = dia_list("create a swap partition", 36, NULL, items2, 
last_item2, align_left);
+          if(i > 0 && values2[i - 1]) {
+            str_copy(&last_part, values2[i - 1]);
+            dev = long_dev(values2[i - 1]);
+            sprintf(buf, "Warning: all data on %s will be deleted!", dev);
+            j = dia_contabort(buf, NO);
+            if(j == YES) {
+              sprintf(buf, "/sbin/mkswap %s", dev);
+              if(!lxrc_run(buf)) {
+                log_info("swapon %s\n", dev);
+                if(swapon(dev, 0)) {
+                  log_info("swapon: ");
+                  perror_info(dev);
+                  dia_message("Error activating swap space.", MSGTYPE_ERROR);
+                }
+                else {
+                  rc = 0;
+                }
               }
               else {
-                rc = 0;
+                dia_message("mkswap failed", MSGTYPE_ERROR);
               }
             }
             else {
-              dia_message("mkswap failed", MSGTYPE_ERROR);
+              rc = 1;
             }
           }
-          else {
-            rc = 1;
-          }
         }
+        while(rc && i);
       }
-      while(rc && i);
-    }
-    else if(i == item_mk_file) {
-      do {
-        i = dia_list("select partition for swap file", 36, NULL, items3, 
last_item3, align_left);
-        if(i > 0 && values3[i - 1]) {
-          str_copy(&last_part, values3[i - 1]);
-          dev = long_dev(values3[i - 1]);
-          util_fstype(dev, &module);
-          if(module) mod_modprobe(module, NULL);
-          j = util_mount_rw(dev, config.mountpoint.swap, NULL);
-          if(j) {
-            dia_message("mount failed", MSGTYPE_ERROR);
-          }
-          else {
-            char *tmp, file[256];
-            int fd;
-            window_t win;
-            unsigned swap_size = config.swap_file_size << (20 - 18);   /* in 
256k chunks */
-
-            sprintf(file, "%s/suseswap.img", config.mountpoint.swap);
-
-            tmp = calloc(1, 1 << 18);
-
-            fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-            if(fd >= 0) {
-              sprintf(buf, "creating swap file 'suseswap.img' (%u MB)", 
config.swap_file_size);
-              dia_status_on(&win, buf);
-              for(j = 0; j < swap_size; j++) {
-                if(write(fd, tmp, 1 << 18) != 1 << 18) break;
-                fsync(fd);
-                dia_status(&win, (j + 1) * 100 / swap_size);
-              }
-              close(fd);
-              dia_status_off(&win);
-            }
-            free(tmp);
-
-            if(j != swap_size) {
-              dia_message("failed to create swapfile", MSGTYPE_ERROR);
+      else if(i == item_mk_file) {
+        do {
+          i = dia_list("select partition for swap file", 36, NULL, items3, 
last_item3, align_left);
+          if(i > 0 && values3[i - 1]) {
+            str_copy(&last_part, values3[i - 1]);
+            dev = long_dev(values3[i - 1]);
+            util_fstype(dev, &module);
+            if(module) mod_modprobe(module, NULL);
+            j = util_mount_rw(dev, config.mountpoint.swap, NULL);
+            if(j) {
+              dia_message("mount failed", MSGTYPE_ERROR);
             }
             else {
-              sprintf(buf, "/sbin/mkswap %s", file);
-              if(!lxrc_run(buf)) {
-                log_info("swapon %s\n", file);
-                if(swapon(file, 0)) {
-                  log_info("swapon: ");
-                  perror_info(file);
-                  dia_message("Error activating swap space.", MSGTYPE_ERROR);
-                }
-                else {
-                  umount2(config.mountpoint.swap, MNT_DETACH);
-                  rc = 0;
+              char *tmp, file[256];
+              int fd;
+              window_t win;
+              unsigned swap_size = config.swap_file_size << (20 - 18); /* in 
256k chunks */
+
+              sprintf(file, "%s/suseswap.img", config.mountpoint.swap);
+
+              tmp = calloc(1, 1 << 18);
+
+              fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+              if(fd >= 0) {
+                sprintf(buf, "creating swap file 'suseswap.img' (%u MB)", 
config.swap_file_size);
+                dia_status_on(&win, buf);
+                for(j = 0; j < swap_size; j++) {
+                  if(write(fd, tmp, 1 << 18) != 1 << 18) break;
+                  fsync(fd);
+                  dia_status(&win, (j + 1) * 100 / swap_size);
                 }
+                close(fd);
+                dia_status_off(&win);
+              }
+              free(tmp);
+
+              if(j != swap_size) {
+                dia_message("failed to create swapfile", MSGTYPE_ERROR);
               }
               else {
-                dia_message("mkswap failed", MSGTYPE_ERROR);
+                sprintf(buf, "/sbin/mkswap %s", file);
+                if(!lxrc_run(buf)) {
+                  log_info("swapon %s\n", file);
+                  if(swapon(file, 0)) {
+                    log_info("swapon: ");
+                    perror_info(file);
+                    dia_message("Error activating swap space.", MSGTYPE_ERROR);
+                  }
+                  else {
+                    umount2(config.mountpoint.swap, MNT_DETACH);
+                    rc = 0;
+                  }
+                }
+                else {
+                  dia_message("mkswap failed", MSGTYPE_ERROR);
+                }
               }
+              if(rc) util_umount(config.mountpoint.swap);
             }
-            if(rc) util_umount(config.mountpoint.swap);
           }
         }
+        while(rc && i);
       }
-      while(rc && i);
     }
   }
   else {
@@ -616,6 +695,8 @@
     }
   }
 
+  slist_free(device_list);
+
   for(i = 0; i < item_cnt1; i++) { free(items1[i]); free(values1[i]); }
   free(items1);
   free(values1);
@@ -698,7 +779,57 @@
     url_free(config.url.install);
     config.url.install = url_set("hd:");
     str_copy(&config.url.install->device, device);
-    str_copy(&config.url.install->path, path);
+    str_copy(&config.url.install->path, path ?: "/");
+    str_copy(&config.url.install->used.device, long_dev(device));
+
+    err = auto2_find_repo() ? 0 : 1;
+  }
+
+  str_copy(&device, NULL);
+  str_copy(&path, NULL);
+
+  return err;
+}
+
+
+/*
+ * Select and mount local repo.
+ *
+ * return:
+ *   0: ok
+ *   1: failed
+ */
+int inst_do_mountable(instmode_t scheme)
+{
+  int err = 0;
+  char *device = NULL, *path = NULL;
+
+  if(net_config_needed(0) && net_config()) return 1;
+
+  if(
+    config.url.install &&
+    config.url.install->scheme == scheme
+  ) {
+    str_copy(&device, config.url.install->device);
+    str_copy(&path, config.url.install->path);
+  }
+
+  if(url_is_blockdev(scheme)) {
+    if(inst_choose_partition(&device, ICP_BLOCK_ALL, "Choose disk / 
partition.", "Enter the device name (e.g., /dev/sda1)")) err = 1;
+  }
+
+  if(!err && !url_is_nopath(scheme)) {
+    if(dia_input2("Enter the source directory.", &path, 30, 0)) err = 1;
+  }
+
+  if(!err) {
+    char *tmp_url = NULL;
+    strprintf(&tmp_url, "%s:", url_scheme2name(scheme));
+    url_free(config.url.install);
+    config.url.install = url_set(tmp_url);
+    str_copy(&tmp_url, NULL);
+    str_copy(&config.url.install->device, device);
+    str_copy(&config.url.install->path, path ?: "/");
     str_copy(&config.url.install->used.device, long_dev(device));
 
     err = auto2_find_repo() ? 0 : 1;
@@ -747,7 +878,7 @@
   }
 
   /* server name */
-  strprintf(&buf, "Enter the name of the %s server.", 
get_instmode_name_up(scheme));
+  strprintf(&buf, "Enter the name of the %s server.", 
url_scheme2name_upper(scheme));
   if(net_get_address2(buf, &server, 1, &n_user, &n_password, &n_port)) err = 1;
   if(!err && n_port) port = n_port;
 
@@ -758,11 +889,11 @@
   if(!err && dia_input2("Enter the directory on the server.", &path, 30, 0)) 
err = 1;
 
   /* user, password */
-  if(!err && (scheme == inst_http || scheme == inst_https || scheme == 
inst_ftp)) {
+  if(!err && url_is_auth(scheme)) {
     if(!n_user) {
       strprintf(&buf,
         "Do you need a username and password to access the %s server?",
-        get_instmode_name_up(scheme)
+        url_scheme2name_upper(scheme)
       );
       i = dia_yesno(buf, NO);
 
@@ -775,8 +906,8 @@
           str_copy(&password, NULL);
         }
         else {
-          strprintf(&buf, "Enter the user name with which to access the %s 
server.", get_instmode_name_up(scheme));
-          strprintf(&buf2, "Enter the password for the %s server.", 
get_instmode_name_up(scheme));
+          strprintf(&buf, "Enter the user name with which to access the %s 
server.", url_scheme2name_upper(scheme));
+          strprintf(&buf2, "Enter the password for the %s server.", 
url_scheme2name_upper(scheme));
           if(
             dia_input2(buf, &user, 20, 0) ||
             dia_input2(buf2, &password, 20, 1)
@@ -825,20 +956,20 @@
       str_copy(&proxy_password, config.url.proxy->password);
     }
 
-    strprintf(&buf, "Use a %s proxy?", get_instmode_name_up(inst_http));
+    strprintf(&buf, "Use a %s proxy?", url_scheme2name_upper(inst_http));
     i = dia_yesno(buf, NO);
     if(i == ESCAPE) {
       err = 1;
     }
     else if(i == YES) {
       /* new proxy */
-      strprintf(&buf, "Enter the name of the %s proxy.", 
get_instmode_name_up(inst_http));
+      strprintf(&buf, "Enter the name of the %s proxy.", 
url_scheme2name_upper(inst_http));
       if(net_get_address2(buf, &proxy, 1, &n_user, &n_password, &n_port)) err 
= 1;
 
       if(!err) {
         if(!n_port) {
           strprintf(&buf2, "%u", proxy_port);
-          strprintf(&buf, "Enter the port of the %s proxy.", 
get_instmode_name_up(inst_http));
+          strprintf(&buf, "Enter the port of the %s proxy.", 
url_scheme2name_upper(inst_http));
           if(dia_input2(buf, &buf2, 6, 0)) err = 1;
           if(!err) {
             u = strtoul(buf2, &s, 0);
@@ -910,10 +1041,10 @@
     url_free(config.url.install);
 
     if(server.name && strchr(server.name, ':')) {
-      strprintf(&buf, "%s://[%s]", get_instmode_name(scheme), server.name);
+      strprintf(&buf, "%s://[%s]", url_scheme2name(scheme), server.name);
     }
     else {
-      strprintf(&buf, "%s://%s", get_instmode_name(scheme), server.name);
+      strprintf(&buf, "%s://%s", url_scheme2name(scheme), server.name);
     }
     config.url.install = url_set(buf);
 
@@ -1436,7 +1567,7 @@
   }
 
   do {
-    j = inst_choose_partition(&partition, 1, "To continue, activate some swap 
space.", "Enter the swap partition (e.g., /dev/sda2)");
+    j = inst_choose_partition(&partition, ICP_SWAP, "To continue, activate 
some swap space.", "Enter the swap partition (e.g., /dev/sda2)");
 
     if(j == 0 && partition) {
       argv[1] = long_dev(partition);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/install.h new/linuxrc-5.0.72/install.h
--- old/linuxrc-5.0.71/install.h        2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/install.h        2016-02-18 11:18:29.000000000 +0100
@@ -8,5 +8,5 @@
 
 int inst_menu(void);
 int inst_start_install(void);
-int inst_choose_partition(char **partition, int swap, char *txt_menu, char 
*txt_input);
+int inst_choose_partition(char **partition, int flags, char *txt_menu, char 
*txt_input);
 int inst_update_cd(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/linuxrc.c new/linuxrc-5.0.72/linuxrc.c
--- old/linuxrc-5.0.71/linuxrc.c        2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/linuxrc.c        2016-02-18 11:18:29.000000000 +0100
@@ -1011,6 +1011,8 @@
   /* look for driver updates in initrd */
   util_chk_driver_update("/", "/");
 
+  url_register_schemes();
+
   util_update_disk_list(NULL, 1);
   util_update_cdrom_list();
 
@@ -1471,11 +1473,18 @@
         str_copy(&sl->key, NULL);
       }
       if(!fork()) {
-        for(i = 0; i < 256; i++) close(i);
-        open("/tmp/extend.log", O_RDWR | O_CREAT | O_TRUNC, 0644);
-        dup(0);
-        dup(0);
-        setlinebuf(stderr);
+        config.extend_running = 1;
+
+        log_debug("=== extend started ===\n");
+
+        for(i = 0; i < 3; i++) close(i);
+
+        // get us a copy of the logs
+        unlink("/tmp/extend.log");
+        str_copy(&config.log.dest[1].name, "/tmp/extend.log");
+        config.log.dest[1].f = NULL;
+        config.log.dest[1].level = LOG_LEVEL_SHOW | LOG_LEVEL_INFO | 
LOG_LEVEL_DEBUG | LOG_TIMESTAMP;
+
         config.download.cnt = 1000 + extend_cnt;
         config.mountpoint.cnt = 1000 + extend_cnt;
         if(!config.debug) config.debug = 1;
@@ -1485,11 +1494,13 @@
         config.secure_always_fail = 1;
 
         if(task == 'a' && sl) {
-          log_info("instsys extend: add %s\n%s: already added\n", ext, ext);
+          log_info("instsys extend: add %s\n", ext);
+          log_info("%s: already added\n", ext, ext);
           err = 0;
         }
         else if(task == 'r' && !sl) {
-          log_info("instsys extend: remove %s\n%s: not there\n", ext, ext);
+          log_info("instsys extend: remove %s\n", ext);
+          log_info("%s: not there\n", ext);
           err = 0;
         }
         else if(task == 'a') {
@@ -1501,6 +1512,10 @@
         f = fopen("/tmp/extend.result", "w");
         if(f) fprintf(f, "%d\n", err);
         fclose(f);
+
+        config.log.dest[1].level = 0;
+        log_debug("=== extend finished ===\n");
+
         if(extend_pid > 0) kill(extend_pid, SIGUSR1);
         exit(0);
       }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/url.c new/linuxrc-5.0.72/url.c
--- old/linuxrc-5.0.71/url.c    2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/url.c    2016-02-18 11:18:29.000000000 +0100
@@ -16,6 +16,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <dirent.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
@@ -53,6 +54,7 @@
 static int url_progress_cb(void *clientp, double dltotal, double dlnow, double 
ultotal, double ulnow);
 
 static int url_read_file_nosig(url_t *url, char *dir, char *src, char *dst, 
char *label, unsigned flags);
+static int url_mount_really(url_t *url, char *device, char *dir);
 static int url_mount_disk(url_t *url, char *dir, int (*test_func)(url_t *));
 static int url_progress(url_data_t *url_data, int stage);
 static int url_setup_device(url_t *url);
@@ -74,7 +76,7 @@
 static int is_gpg_signed(char *file);
 static int is_rpm_signed(char *file);
 static int is_signed(char *file, int check);
-
+static unsigned url_scheme_attr(instmode_t scheme, char *attr_name);
 
 void url_read(url_data_t *url_data)
 {
@@ -364,8 +366,7 @@
   if((s1 = strchr(s0, ':'))) {
     *s1++ = 0;
 
-    i = file_sym2num(s0);
-    url->scheme = i >= 0 ? i : inst_none;
+    url->scheme = url_scheme2id(s0);
 
     if(url->scheme) {
       s0 = s1;
@@ -479,15 +480,10 @@
     }
   }
 
-  /* disk/cdrom: allow path to begin with device name */
+  /* local storage device: allow path to begin with device name */
   if(
-    (
-      url->scheme == inst_disk ||
-      url->scheme == inst_cdrom ||
-      url->scheme == inst_dvd ||
-      url->scheme == inst_floppy ||
-      url->scheme == inst_hd
-    ) && url->path
+    url->is.blockdev &&
+    url->path
   ) {
     tmp = malloc(strlen(url->path) + 6);
     strcpy(tmp, "/");
@@ -544,31 +540,13 @@
     url->quiet = strtoul(sl->value, NULL, 0);
   }
 
-  if(
-    url->scheme == inst_file ||
-    url->scheme == inst_nfs ||
-    url->scheme == inst_smb ||
-    url->scheme == inst_cdrom ||
-    url->scheme == inst_floppy ||
-    url->scheme == inst_hd ||
-    url->scheme == inst_disk ||
-    url->scheme == inst_dvd ||
-    url->scheme == inst_exec
-    ) {
-    url->is.mountable = 1;
-  }
+  url->is.mountable = url_is_mountable(url->scheme);
 
-  if(
-    url->scheme == inst_slp ||
-    url->scheme == inst_nfs ||
-    url->scheme == inst_ftp ||
-    url->scheme == inst_smb ||
-    url->scheme == inst_http ||
-    url->scheme == inst_https ||
-    url->scheme == inst_tftp
-    ) {
-    url->is.network = 1;
-  }
+  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);
 
   if(
     url->scheme == inst_cdrom ||
@@ -592,7 +570,7 @@
   log_debug("url = %s\n", url->str);
 
   if(config.debug >= 2) {
-    log_debug("  scheme = %s (%d)", get_instmode_name(url->scheme), 
url->scheme);
+    log_debug("  scheme = %s (%d)", url_scheme2name(url->scheme), url->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);
@@ -614,8 +592,9 @@
     }
 
     log_debug(
-      "  network = %u, mountable = %u, file = %u, all = %u, quiet = %u\n",
-      url->is.network, url->is.mountable, url->is.file, url->search_all, 
url->quiet
+      "  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,
+      url->search_all, url->quiet
     );
 
     if(url->instsys) log_debug("  instsys = %s\n", url->instsys);
@@ -659,7 +638,7 @@
   if(format == 4) return url_print_zypp(url);
 
   if(format != 3 || url->scheme != inst_rel) {
-    strprintf(&buf, "%s:", get_instmode_name(url->scheme));
+    strprintf(&buf, "%s:", url_scheme2name(url->scheme));
   }
   else {
     str_copy(&buf, "");
@@ -738,6 +717,12 @@
   // log_info("start buf = %p\n", buf);
   // LXRC_WAIT
 
+  if(url->rewrite_for_zypp) {
+    str_copy(&buf, url->rewrite_for_zypp);
+
+    return buf;
+  }
+
   str_copy(&buf, NULL);
 
   str_copy(&path, url->path);
@@ -769,7 +754,7 @@
     scheme != inst_tftp
   ) return buf;
 
-  strprintf(&buf, "%s:", get_instmode_name(scheme));
+  strprintf(&buf, "%s:", url_scheme2name(scheme));
 
   if(url->domain || url->user || url->password || url->server || url->port) {
     strprintf(&buf, "%s//", buf);
@@ -1106,6 +1091,91 @@
 
 
 /*
+ * Really mount 'device' to 'dir' (do an actual mount() call).
+ *
+ * Get additionally needed params out of 'url'.
+ *
+ * Return 0 if ok, else some error code.
+ */
+int url_mount_really(url_t *url, char *device, char *dir)
+{
+  int err = -1;
+
+  slist_t *options_sl = slist_getentry(url->query, "options");
+  char *options = options_sl ? options_sl->value : NULL;
+
+  if(!url->is.mountable) return err;
+
+  if(url->scheme >= inst_extern) {
+    // run external script
+    char *cmd = NULL;
+    char *zypp_file = "/tmp/zypp.url";
+
+    strprintf(&cmd, "/scripts/url/%s/mount", url_scheme2name(url->scheme));
+
+    if(device) setenv("url_device", device, 1);
+    if(dir) setenv("url_dir", dir, 1);
+    if(options) setenv("url_options", options, 1);
+    if(url->server) setenv("url_server", url->server, 1);
+    if(url->path) setenv("url_path", url->path, 1);
+    if(url->user) setenv("url_user", url->user, 1);
+    if(url->password) setenv("url_password", url->password, 1);
+
+    // we don't need rewritten urls for 'extend'
+    if(!config.extend_running) setenv("url_zypp", zypp_file, 1);
+
+    err = lxrc_run(cmd);
+
+    if(!err) {
+      char *s = util_get_attr(zypp_file);
+      if(*s) {
+        str_copy(&url->rewrite_for_zypp, s);
+        log_info("url for zypp: %s", url->rewrite_for_zypp);
+      }
+    }
+
+    unlink(zypp_file);
+
+    unsetenv("url_device");
+    unsetenv("url_dir");
+    unsetenv("url_options");
+    unsetenv("url_server");
+    unsetenv("url_path");
+    unsetenv("url_rewrite");
+    unsetenv("url_user");
+    unsetenv("url_password");
+    unsetenv("url_zypp");
+
+    str_copy(&cmd, NULL);
+  }
+  else {
+    if(!url->is.network) {
+      err = util_mount_ro(device, dir, url->file_list);
+    }
+    else {
+      switch(url->scheme) {
+        case inst_nfs:
+          err = net_mount_nfs(dir, url->server, device, url->port, options);
+          break;
+
+        case inst_smb:
+          err = net_mount_cifs(dir, url->server, device, url->user, 
url->password, url->domain, options);
+          break;
+
+        default:
+          log_info("%s: unsupported scheme\n", url_scheme2name(url->scheme));
+          break;
+      }
+    }
+  }
+
+  log_info("%s: %s -> %s (%d)\n", url_scheme2name(url->scheme), device ?: "", 
dir, err);
+
+  return err;
+}
+
+
+/*
  * Mount url to dir; if dir is NULL, assign temporary mountpoint.
  *
  * If test_func() is set it must return:
@@ -1128,14 +1198,14 @@
   char *path = NULL, *buf = NULL, *s;
   url_t *tmp_url;
 
-  log_info("url mount: trying %s\n", url_print(url, 0));
+  log_info("url mount: trying %s (path = %s)\n", url_print(url, 0), url->path 
?: "");
   if(url->used.model) log_info("(%s)\n", url->used.model);
 
   if(
     !url ||
     !url->scheme ||
     !url->path ||
-    (!url->used.device && url->scheme != inst_file)
+    !(url->used.device || url->is.nodevneeded)
   ) return 0;
 
   url_umount(url);
@@ -1148,9 +1218,12 @@
     /* local device */
 
     /* we might need an extra mountpoint */
-    if(url->scheme != inst_file && strcmp(url->path, "/")) {
+    if(
+      (url->scheme != inst_file && strcmp(url->path, "/")) ||
+      url->scheme >= inst_extern
+    ) {
       str_copy(&url->tmp_mount, new_mountpoint());
-      ok = util_mount_ro(url->used.device, url->tmp_mount, url->file_list) ? 0 
: 1;
+      ok = url_mount_really(url, url->used.device, url->tmp_mount) ? 0 : 1;
 
       if(!ok) {
         log_info("disk: %s: mount failed\n", url->used.device);
@@ -1173,9 +1246,6 @@
   else {
     /* network device */
 
-    slist_t *options_sl = slist_getentry(url->query, "options");
-    char *options = options_sl ? options_sl->value : NULL;
-
     switch(url->scheme) {
       case inst_nfs:
         str_copy(&url->mount, dir ?: new_mountpoint());
@@ -1183,8 +1253,7 @@
         log_debug("[server = %s]\n", url->server ?: "");
 
         if(!url->is.file) {
-          err = net_mount_nfs(url->mount, url->server, url->path, url->port, 
options);
-          log_info("nfs: %s -> %s (%d)\n", url->path, url->mount, err);
+          err = url_mount_really(url, url->path, url->mount);
         }
         else {
           log_info("nfs: %s: is file, mounting one level up\n", url->path);
@@ -1200,8 +1269,7 @@
 
             log_debug("[server = %s]\n", url->server ?: "");
 
-            err = net_mount_nfs(url->tmp_mount, url->server, buf, url->port, 
options);
-            log_info("nfs: %s -> %s (%d)\n", buf, url->tmp_mount, err);
+            err = url_mount_really(url, buf, url->tmp_mount);
     
             if(err) {
               log_info("nfs: %s: mount failed\n", url->used.device);
@@ -1231,9 +1299,10 @@
 
         log_debug("[server = %s]\n", url->server ?: "");
 
-        err = net_mount_cifs(s, url->server, url->share, url->user, 
url->password, url->domain, options);
-        log_info("cifs: %s -> %s (%d)\n", url->share, s, err);
+        err = url_mount_really(url, url->share, s);
+
         if(err) {
+          log_info("cifs: %s: mount failed\n", url->used.device);
           str_copy(&url->tmp_mount, NULL);
           str_copy(&url->mount, NULL);
         }
@@ -1254,8 +1323,19 @@
         break;
 
       default:
-        log_info("%s: unsupported scheme\n", get_instmode_name(url->scheme));
-        err = 1;
+        if(url_is_mountable(url->scheme)) {
+          str_copy(&url->tmp_mount, new_mountpoint());
+          err = url_mount_really(url, url->used.device, url->tmp_mount);
+
+          if(err) {
+            log_info("disk: %s: mount failed\n", url->used.device);
+            str_copy(&url->tmp_mount, NULL);
+          }
+        }
+        else {
+          log_info("%s: unsupported scheme\n", url_scheme2name(url->scheme));
+          err = 1;
+        }
         break;
     }
   }
@@ -1362,10 +1442,8 @@
 
   if(!config.hd_data) return 1;
 
-  if(
-    url->scheme == inst_file ||
-    url->used.device
-  ) {
+  // we either don't need to setup/select a device or have already done so
+  if(url->is.nodevneeded || url->used.device) {
     return url_mount_disk(url, dir, test_func) ? 0 : 1;
   }
 
@@ -2445,11 +2523,11 @@
   int ok = 0;
   char *type;
 
-  // log_info("*** url_setup_device(%s)\n", url_print(url, 0));
+  log_info("url_setup_device: %s\n", url_print(url, 0));
 
   if(!url) return 0;
 
-  if(url->scheme == inst_file) return 1;
+  if(url->is.nodevneeded) return 1;
 
   if(!url->used.device) return 0;
 
@@ -2974,3 +3052,228 @@
   return ok;
 }
 
+
+/*
+ * Return 1 if we can mount the url.
+ */
+unsigned url_is_mountable(instmode_t scheme)
+{
+  if(
+    scheme == inst_file ||
+    scheme == inst_nfs ||
+    scheme == inst_smb ||
+    scheme == inst_cdrom ||
+    scheme == inst_floppy ||
+    scheme == inst_hd ||
+    scheme == inst_disk ||
+    scheme == inst_dvd ||
+    scheme == inst_exec
+  ) {
+    return 1;
+  }
+
+  return url_scheme_attr(scheme, "mount");
+}
+
+
+/*
+ * Return 1 if we need network for this url scheme.
+ */
+unsigned url_is_network(instmode_t scheme)
+{
+  if(
+    scheme == inst_slp ||
+    scheme == inst_nfs ||
+    scheme == inst_ftp ||
+    scheme == inst_smb ||
+    scheme == inst_http ||
+    scheme == inst_https ||
+    scheme == inst_tftp
+  ) {
+    return 1;
+  }
+
+  return url_scheme_attr(scheme, "network");
+}
+
+
+/*
+ * Return 1 if url scheme needs a local block device.
+ *
+ * (In this case, the path component of the url may optionally start the
+ * device name.)
+ *
+ */
+unsigned url_is_blockdev(instmode_t scheme)
+{
+  if(
+    scheme == inst_disk ||
+    scheme == inst_cdrom ||
+    scheme == inst_dvd ||
+    scheme == inst_floppy ||
+    scheme == inst_hd
+  ) {
+    return 1;
+  }
+
+  return url_scheme_attr(scheme, "blockdev");
+}
+
+
+/*
+ * Return 1 if url scheme does not have a path component.
+ *
+ */
+unsigned url_is_nopath(instmode_t scheme)
+{
+  if(
+    scheme == inst_slp
+  ) {
+    return 1;
+  }
+
+  return url_scheme_attr(scheme, "nopath");
+}
+
+
+/*
+ * Return 1 if url scheme may need user/password.
+ *
+ */
+unsigned url_is_auth(instmode_t scheme)
+{
+  if(
+    scheme == inst_ftp ||
+    scheme == inst_smb ||
+    scheme == inst_http ||
+    scheme == inst_https
+  ) {
+    return 1;
+  }
+
+  return url_scheme_attr(scheme, "auth");
+}
+
+
+/*
+ * Check for presence of file 'attr_name' in URL directory.
+ */
+unsigned url_scheme_attr(instmode_t scheme, char *attr_name)
+{
+  int ok = 0;
+
+  if(scheme >= inst_extern && attr_name && *attr_name) {
+    char *path = NULL;
+
+    strprintf(&path, "/scripts/url/%s/%s", url_scheme2name(scheme), attr_name);
+    ok = util_check_exist(path) ? 1 : 0;
+
+    str_copy(&path, NULL);
+  }
+
+  return ok;
+}
+
+
+/*
+ * Convert URL scheme to internal number.
+ *
+ * Note: if the URL scheme is an externally supported one (via "/scripts/url")
+ * it is regsitered and gets assigned an id.
+ */
+instmode_t url_scheme2id(char *scheme)
+{
+  int i;
+  slist_t *sl;
+
+  if(!scheme || !*scheme) return inst_none;
+
+  i = file_sym2num(scheme);
+
+  if(i >= 0) return i;
+
+  if(util_check_exist2("/scripts/url", scheme) == 'd') {
+    char *attr = NULL, *attr_val;
+    strprintf(&attr, "/scripts/url/%s/menu", scheme);
+    attr_val = util_get_attr(attr);
+    str_copy(&attr, NULL);
+    if(!slist_getentry(config.extern_scheme, scheme)) {
+      log_info("registering url scheme: %s: %s\n", scheme, attr_val);
+    }
+    sl = slist_setentry(&config.extern_scheme, scheme, *attr_val ? attr_val : 
NULL, 1);
+  }
+
+  for(sl = config.extern_scheme, i = inst_extern; sl; sl = sl->next, i++) {
+    if(!strcmp(sl->key, scheme)) return i;
+  }
+
+  return inst_none;
+}
+
+
+/*
+ * String representing the URL scheme.
+ *
+ * Returns NULL if scheme is unknown.;
+ */
+char *url_scheme2name(instmode_t scheme_id)
+{
+  char *s = NULL;
+  slist_t *sl;
+  instmode_t i;
+
+  if(scheme_id < inst_extern) {
+    s = file_num2sym("no scheme", scheme_id);
+  }
+  else {
+    for(sl = config.extern_scheme, i = inst_extern; sl; sl = sl->next, i++) {
+      if(i == scheme_id) {
+        s = sl->key;
+        break;
+      }
+    }
+  }
+
+  return s;
+}
+
+
+/*
+ * Uppercase variant of URL scheme; used in messages.
+ */
+char *url_scheme2name_upper(instmode_t scheme_id)
+{
+  static char *name = NULL;
+  int i;
+
+  str_copy(&name, url_scheme2name(scheme_id));
+
+  if(name) {
+    for(i = 0; name[i]; i++) name[i] = toupper(name[i]);
+  }
+
+  return name;
+}
+
+
+/*
+ * Register all user-defined schemes.
+ *
+ * Each scheme is auto-registered on first use. But to get the menus in
+ * manual mode right, we register all in one go.
+ */
+void url_register_schemes()
+{
+  struct dirent *de;
+  DIR *d;
+
+ if((d = opendir("/scripts/url"))) {
+    while((de = readdir(d))) {
+      if(de->d_name[0] != '.') {
+        url_scheme2id(de->d_name);
+      }
+    }
+    closedir(d);
+  }
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/url.h new/linuxrc-5.0.72/url.h
--- old/linuxrc-5.0.71/url.h    2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/url.h    2016-02-18 11:18:29.000000000 +0100
@@ -76,3 +76,13 @@
 char *url_print2(url_t *url, char *file);
 char *url_instsys_base(char *path);
 void url_build_instsys_list(char *instsys, int read_list);
+
+unsigned url_is_mountable(instmode_t scheme);
+unsigned url_is_network(instmode_t scheme);
+unsigned url_is_blockdev(instmode_t scheme);
+unsigned url_is_nopath(instmode_t scheme);
+unsigned url_is_auth(instmode_t scheme);
+instmode_t url_scheme2id(char *scheme);
+char *url_scheme2name(instmode_t scheme_id);
+char *url_scheme2name_upper(instmode_t scheme_id);
+void url_register_schemes(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/user_defined_url_schemes.txt 
new/linuxrc-5.0.72/user_defined_url_schemes.txt
--- old/linuxrc-5.0.71/user_defined_url_schemes.txt     1970-01-01 
01:00:00.000000000 +0100
+++ new/linuxrc-5.0.72/user_defined_url_schemes.txt     2016-02-18 
11:18:29.000000000 +0100
@@ -0,0 +1,59 @@
+User-defined URl schemes
+========================
+
+[Note: the 'get' part has not been implemented yet]
+
+You can add URL schemes to linuxrc that can be used with the
+'install', 'info', 'dud', and 'autoyast2' options.
+
+Also, it can show up in the linuxrc menus when linuxrc is run in manual
+mode.
+
+linuxrc supports two kinds of url schemes: (1) mountable and (2)
+downloadable schemes. For (1), the url points to some directory structure
+that can be mounted. For (2), only individual files can be accessed 
(downloaded).
+
+To define a url scheme, create (in the initrd) a directory below /scripts
+with the name of the scheme (e.g. 'foo'). Then put an executable script
+named 'mount' (for case (1)) or 'get' (for case (2)) into this directory.
+
+Optionally put any of the following (possibly empty) files into that
+directory:
+
+- 'network' to indicate that the network should be set up; linuxrc may try
+  this url configuring all available network interfaces in turn
+
+- 'blockdev' to indicate that linuxrc can try this url on all block devices
+  (including partitions); the name of the current block device is passed to
+  the script
+
+- 'nopath' to indicate that no path component is required (linuxrc will not
+  ask for a path in manual mode)
+
+- 'auth' to indicate the url accepts user/password (linuxrc will ask for them
+  in manual mode)
+
+- 'network' and 'blockdev' are mutually exclusive
+
+The 'mount'/'get' scripts are passed parameters via environment variables:
+
+url_device:    current block device / network interface (if any)
+url_dir:       where to mount the url to
+url_options:   anything passed via '?options' in the url
+url_server:    the server part of the url
+url_path:      the path part of the url
+url_user:       user name for authentication (if any)
+url_password:   password for authentication (if any)
+url_zypp:       if set, the name of a file; anything written into that file
+               will constitute the url passed to zypp later; zypp has a
+               different set of url schemes than linuxrc; use this file
+               to rewrite the url into zypp form;
+               *note*: var might be unset - in this case rewritten url is
+               not needed
+
+The script should exit with 0 to indicate that it was successful.
+
+The 'mount' script is expected to mount the url to $url_dir. It should
+preferably be mounted read-only. *Note*: it must be possible to mount
+the url to different directories at the same time.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/util.c new/linuxrc-5.0.72/util.c
--- old/linuxrc-5.0.71/util.c   2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/util.c   2016-02-18 11:18:29.000000000 +0100
@@ -1202,6 +1202,16 @@
   add_flag(&sl0, buf, config.net.sethostname, "hostname");
   if(*buf) slist_append_str(&sl0, buf);
 
+  if(config.extern_scheme) {
+    strcpy(buf, "additional URL schemes:");
+    slist_append_str(&sl0, buf);
+    for(sl = config.extern_scheme; sl; sl = sl->next) {
+      if(!sl->key) continue;
+      sprintf(buf, "  %s: %s", sl->key, sl->value ?: "");
+      slist_append_str(&sl0, buf);
+    }
+  }
+
   sprintf(buf, "net_config_mask = 0x%x", net_config_mask());
   slist_append_str(&sl0, buf);
 
@@ -2521,27 +2531,6 @@
 }
 
 
-char *get_instmode_name(instmode_t instmode)
-{
-  return file_num2sym("no scheme", instmode);
-}
-
-
-char *get_instmode_name_up(instmode_t instmode)
-{
-  static char *name = NULL;
-  int i;
-
-  str_copy(&name, file_num2sym("no scheme", instmode));
-
-  if(name) {
-    for(i = 0; name[i]; i++) name[i] = toupper(name[i]);
-  }
-
-  return name;
-}
-
-
 int util_fstype_main(int argc, char **argv)
 {
   char *s, buf[64], *compr, *archive;
@@ -2773,6 +2762,8 @@
   int err = -1;
   struct stat64 sbuf;
 
+  log_info("mount: dev = %s, dir = %s, flags = 0x%lx\n", dev, dir, flags & 
0xffff);
+
   if(!dev || !dir) return -1;
 
   if(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/linuxrc-5.0.71/util.h new/linuxrc-5.0.72/util.h
--- old/linuxrc-5.0.71/util.h   2016-02-12 10:38:43.000000000 +0100
+++ new/linuxrc-5.0.72/util.h   2016-02-18 11:18:29.000000000 +0100
@@ -65,8 +65,6 @@
 char *inet2print(inet_t *inet);
 void str_copy(char **dst, const char *src);
 void strprintf(char **buf, char *format, ...) __attribute__ ((format (printf, 
2, 3)));
-char *get_instmode_name(instmode_t instmode);
-char *get_instmode_name_up(instmode_t instmode);
 
 void util_free_mem(void);
 void util_update_meminfo(void);


Reply via email to