Commit yaboot 1.3.6-pre2
[yaboot.git] / second / file.c
index 763e3e6ccd3761a90e5004d2975611511e51b9bd..366d5ba9dbff93cf56c7a48c1dbcbbb230802bc2 100644 (file)
@@ -33,33 +33,70 @@ extern char bootdevice[1024];
 /* This function follows the device path in the devtree and separates
    the device name, partition number, and other datas (mostly file name)
    the string passed in parameters is changed since 0 are put in place
-   of some separators to terminate the various strings
- */
+   of some separators to terminate the various strings.  
+
+   when a default device is supplied imagepath will be assumed to be a
+   plain filename unless it contains a : otherwise if defaultdev is
+   NULL imagepath will be assumed to be a device path.
+
+   returns 1 on success 0 on failure.
+
+   Supported examples:
+    - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4
+    - /pci@80000000/pci-bridge@d/ADPT,2930CU@2/@1:4,/boot/vmlinux
+    - hd:3,/boot/vmlinux
+    - enet:10.0.0.1,/tftpboot/vmlinux
+    - enet:,/tftpboot/vmlinux
+    - enet:bootp
+    - enet:0
+   Supported only if defdevice == NULL
+    - disc
+    - any other device path lacking a :
+   Unsupported examples:
+    - hd:2,\\:tbxi <- no filename will be detected due to the extra :
+    - enet:192.168.2.1,bootme,c-iaddr,g-iaddr,subnet-mask,bootp-retries,tftp-retries */
 
 int
 parse_device_path(char *imagepath, char *defdevice, int defpart,
                  char *deffile, struct boot_fspec_t *result)
 {
      char *ptr;
-     char *ipath = strdup(imagepath);
-     char *defdev = strdup(defdevice);
+     char *ipath = NULL;
+     char *defdev = NULL;
 
      result->dev = NULL;
      result->part = -1;
      result->file = NULL;
 
-     if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) {
-         if ((ptr = strrchr(defdev, ':')) != NULL)
-              *ptr = 0; /* remove trailing : from defdevice if necessary */
+     if (!imagepath)
+         return 0;
+     else
+         ipath = strdup(imagepath);
+
+     if (defdevice)
+         defdev = strdup(defdevice);
+
+     if (defdev) {
+         if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) {
+              if ((ptr = strrchr(defdev, ':')) != NULL)
+                   *ptr = 0; /* remove trailing : from defdevice if necessary */
+         }
      }
 
-     if (!imagepath)
-         goto punt;
+     /* if there is no : then there is no filename or partition.  must
+        use strrchr() since enet:,10.0.0.1,file is legal */
 
-     if ((ptr = strrchr(ipath, ',')) != NULL) {
-         result->file = strdup(ptr+1);
-         /* Trim the filename off */
-         *ptr = 0;
+     if (strchr(ipath, ':') != NULL) {
+         if ((ptr = strrchr(ipath, ',')) != NULL) {
+              char *colon = strrchr(ipath, ':');
+              /* If a ':' occurs *after* a ',', then we assume that there is
+                 no filename */
+              if (!colon || colon < ptr) {
+                   result->file = strdup(ptr+1);
+                   /* Trim the filename off */
+                   *ptr = 0;
+              }
+         }
      }
 
      if (strstr(ipath, "ethernet") || strstr(ipath, "enet"))
@@ -73,14 +110,15 @@ parse_device_path(char *imagepath, char *defdevice, int defpart,
          result->dev = strdup(ipath);
          if (*(ptr+1))
               result->part = simple_strtol(ptr+1, NULL, 10);
+     } else if (!defdev) {
+         result->dev = strdup(ipath); 
      } else if (strlen(ipath)) {
           result->file = strdup(ipath);
      } else {
          return 0;
      }
-     
-punt:
-     if (!result->dev)
+
+     if (!result->dev && defdev)
          result->dev = strdup(defdev);
      
      if (result->part < 0)
@@ -88,7 +126,10 @@ punt:
      
      if (!result->file)
          result->file = strdup(deffile);
+
      free(ipath);
+     if (defdev)
+         free(defdev);
      return 1;
 }
 
@@ -213,7 +254,7 @@ int open_file(const struct boot_fspec_t* spec, struct boot_file_t* file)
 
 /* 
  * Local variables:
- * c-file-style: "K&R"
+ * c-file-style: "k&r"
  * c-basic-offset: 5
  * End:
  */