debuggers.hg
changeset 22696:180ad8c642ab
xl: don't segfault parsing disk configs, support NULL physpath and ioemu:
Switch to a state machine parser since it's easier to handle all these
exotic cases without segfaulting. NULL physpaths are now allowed and a
dodgy hack is introduced to skip over the "ioemu:" prefix for a
virtpath. Also fixes a leak of buf2.
Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Switch to a state machine parser since it's easier to handle all these
exotic cases without segfaulting. NULL physpaths are now allowed and a
dodgy hack is introduced to skip over the "ioemu:" prefix for a
virtpath. Also fixes a leak of buf2.
Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author | Gianni Tedesco <gianni.tedesco@citrix.com> |
---|---|
date | Wed Jan 05 23:13:07 2011 +0000 (2011-01-05) |
parents | 39194f457534 |
children | e0db3784a4a2 |
files | tools/libxl/xl_cmdimpl.c |
line diff
1.1 --- a/tools/libxl/xl_cmdimpl.c Wed Jan 05 09:57:15 2011 +0000 1.2 +++ b/tools/libxl/xl_cmdimpl.c Wed Jan 05 23:13:07 2011 +0000 1.3 @@ -641,6 +641,134 @@ static int parse_action_on_shutdown(cons 1.4 return 0; 1.5 } 1.6 1.7 +#define DSTATE_INITIAL 0 1.8 +#define DSTATE_TAP 1 1.9 +#define DSTATE_PHYSPATH 2 1.10 +#define DSTATE_VIRTPATH 3 1.11 +#define DSTATE_VIRTTYPE 4 1.12 +#define DSTATE_RW 5 1.13 +#define DSTATE_TERMINAL 6 1.14 + 1.15 +static int parse_disk_config(libxl_device_disk *disk, char *buf2) 1.16 +{ 1.17 + int state = DSTATE_INITIAL; 1.18 + char *p, *end, *tok; 1.19 + 1.20 + memset(disk, 0, sizeof(*disk)); 1.21 + 1.22 + for(tok = p = buf2, end = buf2 + strlen(buf2) + 1; p < end; p++) { 1.23 + switch(state){ 1.24 + case DSTATE_INITIAL: 1.25 + if ( *p == ':' ) { 1.26 + *p = '\0'; 1.27 + if ( !strcmp(tok, "phy") ) { 1.28 + state = DSTATE_PHYSPATH; 1.29 + disk->phystype = PHYSTYPE_PHY; 1.30 + }else if ( !strcmp(tok, "file") ) { 1.31 + state = DSTATE_PHYSPATH; 1.32 + disk->phystype = PHYSTYPE_FILE; 1.33 + }else if ( !strcmp(tok, "tap") ) { 1.34 + state = DSTATE_TAP; 1.35 + }else{ 1.36 + fprintf(stderr, "Unknown disk type: %s\n", tok); 1.37 + return 0; 1.38 + } 1.39 + tok = p + 1; 1.40 + } 1.41 + break; 1.42 + case DSTATE_TAP: 1.43 + if ( *p == ':' ) { 1.44 + *p = '\0'; 1.45 + if ( !strcmp(tok, "aio") ) { 1.46 + disk->phystype = PHYSTYPE_AIO; 1.47 + }else if ( !strcmp(tok, "vhd") ) { 1.48 + disk->phystype = PHYSTYPE_VHD; 1.49 + }else if ( !strcmp(tok, "qcow") ) { 1.50 + disk->phystype = PHYSTYPE_QCOW; 1.51 + }else if ( !strcmp(tok, "qcow2") ) { 1.52 + disk->phystype = PHYSTYPE_QCOW2; 1.53 + }else { 1.54 + fprintf(stderr, "Unknown tapdisk type: %s\n", tok); 1.55 + return 0; 1.56 + } 1.57 + 1.58 + tok = p + 1; 1.59 + state = DSTATE_PHYSPATH; 1.60 + } 1.61 + break; 1.62 + case DSTATE_PHYSPATH: 1.63 + if ( *p == ',' ) { 1.64 + int ioemu_len; 1.65 + 1.66 + *p = '\0'; 1.67 + disk->physpath = (*tok) ? strdup(tok) : NULL; 1.68 + tok = p + 1; 1.69 + 1.70 + /* hack for ioemu disk spec */ 1.71 + ioemu_len = strlen("ioemu:"); 1.72 + state = DSTATE_VIRTPATH; 1.73 + if ( tok + ioemu_len < end && 1.74 + !strncmp(tok, "ioemu:", ioemu_len)) { 1.75 + tok += ioemu_len; 1.76 + p += ioemu_len; 1.77 + } 1.78 + } 1.79 + break; 1.80 + case DSTATE_VIRTPATH: 1.81 + if ( *p == ',' || *p == ':' || *p == '\0' ) { 1.82 + switch(*p) { 1.83 + case ':': 1.84 + state = DSTATE_VIRTTYPE; 1.85 + break; 1.86 + case ',': 1.87 + state = DSTATE_RW; 1.88 + break; 1.89 + case '\0': 1.90 + state = DSTATE_TERMINAL; 1.91 + break; 1.92 + } 1.93 + if ( tok == p ) 1.94 + goto out; 1.95 + *p = '\0'; 1.96 + disk->virtpath = (*tok) ? strdup(tok) : NULL; 1.97 + tok = p + 1; 1.98 + } 1.99 + break; 1.100 + case DSTATE_VIRTTYPE: 1.101 + if ( *p == ',' || *p == '\0' ) { 1.102 + *p = '\0'; 1.103 + if ( !strcmp(tok, "cdrom") ) { 1.104 + disk->is_cdrom = 1; 1.105 + disk->unpluggable = 1; 1.106 + }else{ 1.107 + fprintf(stderr, "Unknown virtual disk type: %s\n", tok); 1.108 + return 0; 1.109 + } 1.110 + tok = p + 1; 1.111 + state = (*p == ',') ? DSTATE_RW : DSTATE_TERMINAL; 1.112 + } 1.113 + break; 1.114 + case DSTATE_RW: 1.115 + if ( *p == '\0' ) { 1.116 + disk->readwrite = (tok[0] == 'w'); 1.117 + tok = p + 1; 1.118 + state = DSTATE_TERMINAL; 1.119 + } 1.120 + break; 1.121 + case DSTATE_TERMINAL: 1.122 + goto out; 1.123 + } 1.124 + } 1.125 + 1.126 +out: 1.127 + if ( tok != p || state != DSTATE_TERMINAL ) { 1.128 + fprintf(stderr, "parse error in disk config near '%s'\n", tok); 1.129 + return 0; 1.130 + } 1.131 + 1.132 + return 1; 1.133 +} 1.134 + 1.135 static void parse_config_data(const char *configfile_filename_report, 1.136 const char *configfile_data, 1.137 int configfile_len, 1.138 @@ -826,59 +954,13 @@ static void parse_config_data(const char 1.139 while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) { 1.140 libxl_device_disk *disk; 1.141 char *buf2 = strdup(buf); 1.142 - char *p, *p2; 1.143 1.144 d_config->disks = (libxl_device_disk *) realloc(d_config->disks, sizeof (libxl_device_disk) * (d_config->num_disks + 1)); 1.145 disk = d_config->disks + d_config->num_disks; 1.146 - 1.147 - disk->backend_domid = 0; 1.148 - disk->domid = 0; 1.149 - disk->unpluggable = 0; 1.150 - 1.151 - p = strtok(buf2, ",:"); 1.152 - while (*p == ' ') 1.153 - p++; 1.154 - if (!strcmp(p, "phy")) { 1.155 - disk->phystype = PHYSTYPE_PHY; 1.156 - } else if (!strcmp(p, "file")) { 1.157 - disk->phystype = PHYSTYPE_FILE; 1.158 - } else if (!strcmp(p, "tap")) { 1.159 - p = strtok(NULL, ":"); 1.160 - if (!strcmp(p, "aio")) { 1.161 - disk->phystype = PHYSTYPE_AIO; 1.162 - } else if (!strcmp(p, "vhd")) { 1.163 - disk->phystype = PHYSTYPE_VHD; 1.164 - } else if (!strcmp(p, "qcow")) { 1.165 - disk->phystype = PHYSTYPE_QCOW; 1.166 - } else if (!strcmp(p, "qcow2")) { 1.167 - disk->phystype = PHYSTYPE_QCOW2; 1.168 - } 1.169 + if ( !parse_disk_config(disk, buf2) ) { 1.170 + exit(1); 1.171 } 1.172 - p = strtok(NULL, ","); 1.173 - while (*p == ' ') 1.174 - p++; 1.175 - disk->physpath= strdup(p); 1.176 - p = strtok(NULL, ","); 1.177 - while (*p == ' ') 1.178 - p++; 1.179 - p2 = strchr(p, ':'); 1.180 - if (p2 == NULL) { 1.181 - disk->virtpath = strdup(p); 1.182 - disk->is_cdrom = 0; 1.183 - disk->unpluggable = 1; 1.184 - } else { 1.185 - *p2 = '\0'; 1.186 - disk->virtpath = strdup(p); 1.187 - if (!strcmp(p2 + 1, "cdrom")) { 1.188 - disk->is_cdrom = 1; 1.189 - disk->unpluggable = 1; 1.190 - } else 1.191 - disk->is_cdrom = 0; 1.192 - } 1.193 - p = strtok(NULL, ","); 1.194 - while (*p == ' ') 1.195 - p++; 1.196 - disk->readwrite = (p[0] == 'w') ? 1 : 0; 1.197 + 1.198 free(buf2); 1.199 d_config->num_disks++; 1.200 }