1 /*
   2  *  GRUB  --  GRand Unified Bootloader
   3  *  Copyright (C) 2012 Daniil Lunev
   4  *
   5  *  GRUB is free software: you can redistribute it and/or modify
   6  *  it under the terms of the GNU General Public License as published by
   7  *  the Free Software Foundation, either version 3 of the License, or
   8  *  (at your option) any later version.
   9  *
  10  *  GRUB is distributed in the hope that it will be useful,
  11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  *  GNU General Public License for more details.
  14  *
  15  *  You should have received a copy of the GNU General Public License
  16  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  17  */
  18 
  19 #include <grub/types.h>
  20 #include <grub/emu/misc.h>
  21 #include <grub/emu/getroot.h>
  22 #include <grub/fs.h>
  23 #include <grub/device.h>
  24 
  25 #include <stdio.h>
  26 #include <stdlib.h>
  27 #include <string.h>
  28 
  29 #define BUFFER_SIZE 512
  30 
  31 struct commands {
  32   const char * lst;
  33   const char * cfg;
  34 };
  35 
  36 void
  37 get_uuid_by_path(char * path, char ** uuid)
  38 {
  39   char ** devices = NULL;
  40   char * drive = NULL;
  41   grub_device_t dev = NULL;
  42   grub_fs_t fs = NULL;
  43   char * grub_path = NULL;
  44 
  45   grub_path = canonicalize_file_name(path);
  46   if (! grub_path)
  47     grub_util_error("Can't canonicalize path");
  48   
  49   devices = grub_guess_root_devices(grub_path);
  50   if (! devices) 
  51     grub_util_error("Can't find device");
  52   
  53   drive = grub_util_get_grub_dev(devices[0]);
  54   if (! drive)
  55     grub_util_error("Can't get drive");
  56     
  57   dev = grub_device_open(drive);
  58   if (! dev) 
  59     grub_util_error("Can't open device");
  60 
  61   fs = grub_fs_probe(dev);
  62   if (! fs) 
  63     grub_util_error("Probing fs error");
  64 
  65   if (! fs->uuid) 
  66     grub_util_error("This fs doesn't support uuid");
  67 
  68   if (fs->uuid(dev, uuid) != GRUB_ERR_NONE) 
  69     grub_util_error("%s", grub_errmsg);
  70 
  71   free(grub_path);
  72   if (dev) 
  73     grub_device_close(dev);
  74 
  75   return;
  76 }
  77 
  78 struct commands com[] = {
  79   {"title", "entry_name"},
  80   {"findroot", "pool"},
  81   {"bootfs", "data_set"},
  82   {"kernel$", "kernel_path"},
  83   {"module$", "module"},
  84   {"default", "default_entry"},
  85   {"timeout", "timeout"},
  86   {"serial", "serial"},
  87   {"terminal", "terminal"},
  88   {0, 0},
  89 };
  90 
  91 int
  92 get_command_id(char * command)
  93 {
  94   int i = 0;
  95   for (; com[i].lst; ++i)
  96     if (!strcmp(com[i].lst, command))
  97       return i;
  98   return -1;
  99 }
 100 
 101 char *
 102 retrive_value(char * val)
 103 {
 104   char * str; 
 105   int quote_flag = 0;;
 106 
 107   while ((*val == ' ') || (*val == '\t'))
 108     ++val;
 109 
 110   if (*val == '"') {
 111     ++val;
 112     ++quote_flag;  
 113   }
 114   
 115   str = val;
 116   
 117   for (;;) {
 118     if (quote_flag) {
 119       if (*val == '"') 
 120         break;
 121       if (*val == '\0')
 122         return NULL;
 123     } else {
 124       if ((*val == ' ') || (*val == '\t') || (*val == '\0'))
 125         break;
 126     }
 127     ++val;
 128   }
 129   *val = '\0';
 130 
 131   return str;
 132 }
 133 
 134 int
 135 parse_menulst(FILE * in_file, FILE * out_file)
 136 {
 137   char line[BUFFER_SIZE];
 138   char * command;
 139   char * value;
 140   char * label = NULL;
 141   char bootfs[BUFFER_SIZE];
 142   char pool[BUFFER_SIZE];
 143   char * uuid;
 144   char * c;
 145   int com_id;
 146 
 147   for (;;) {
 148     command = fgets(line, BUFFER_SIZE, in_file);
 149     if (! command)
 150       return 0;
 151 
 152     c = command + strlen(command) - 1;
 153     if ((*c != '\n') && (fgets(line, BUFFER_SIZE, in_file)))
 154       return 1;
 155 
 156     if ((*command == '#') || (*command == ' ') 
 157        || (*command == '\t') || (*command == '\n'))
 158       continue;
 159 
 160     if (*c == '\n')
 161       *c = '\0';
 162     value = strchr(line, ' ');
 163     if (! value)
 164       continue;
 165 
 166     *value++ = '\0';
 167     
 168     com_id = get_command_id(command);
 169     if (com_id < 0)
 170       continue;
 171 
 172     switch (com_id) {
 173     case 0:
 174       fprintf(out_file,"\n%s=%s\n", com[com_id].cfg, value);
 175       break;
 176     case 1:
 177       label = strdup(strchr(value, '_') + 1);
 178       c = strchr(label, ',');
 179       if (c)
 180         *c = 0;
 181       continue;
 182     case 2:
 183       c = strchr(value, '/');
 184       if (c != NULL) {
 185         strcpy(bootfs, c);
 186         *c = '\0';
 187         strcpy(pool + 1, value);
 188         *pool = '/';
 189         uuid = NULL;
 190         get_uuid_by_path(pool, &uuid);
 191         if (! uuid)
 192           return 1;
 193       
 194         fprintf(out_file,"pool_uuid=%s\n", uuid);
 195         
 196       } 
 197       *c = '/';
 198       fprintf(out_file,"data_set=%s\n", value);
 199       if (label) {
 200         free(label);
 201         label = NULL;
 202       }
 203       break;
 204     case 3:
 205     case 4:
 206       if (label) {
 207         fprintf(out_file,"pool_label=%s\n", label);
 208         free(label);
 209         label = NULL;
 210       }
 211       if (com_id == 3)
 212         c = strchr (value, ' ');
 213         if (c)
 214           *c = '\0';
 215       if (! value)
 216         return 1;
 217       
 218       fprintf(out_file,"%s=%s\n", com[com_id].cfg, value);
 219 
 220       if ((com_id == 3) && (c)) {
 221         char * tmp;
 222         value = c + 1;
 223         tmp = strstr(value, "ZFS-BOOTFS");
 224         if (tmp)
 225           *(tmp + 3) = '_';
 226         fprintf(out_file,"kernel_options=%s\n", value);
 227       }
 228 
 229       break;
 230     default:
 231       fprintf(out_file,"%s=%s\n", com[com_id].cfg, value);
 232       break;
 233     }
 234   }
 235   return 0;
 236 }
 237 
 238 int
 239 main(int argc, char ** argv)
 240 {
 241   FILE * lst_file;
 242   FILE * cfg_file;
 243   int err = 0;
 244 
 245   if (argc != 3) {
 246     printf("grub-solarislst2cfg lst_file cfg_file\n");
 247     return 1;
 248   }
 249 
 250   lst_file = fopen(argv[1], "r");
 251   if (! lst_file)
 252     return 1;
 253 
 254   cfg_file = fopen(argv[2], "w");
 255   if (! cfg_file) {
 256     fclose(lst_file);
 257     return 1;
 258   }
 259 
 260   grub_util_init_nls();
 261   grub_util_biosdisk_init(DEFAULT_DEVICE_MAP);
 262   grub_init_all();
 263   
 264   err = parse_menulst(lst_file, cfg_file);
 265 
 266   grub_fini_all();
 267 
 268   fclose(lst_file);
 269   fclose(cfg_file);
 270 
 271   if (err)
 272     remove(argv[2]);
 273   return err;
 274 }