/* This file is part of Eclat. Copyright (C) 2013-2018 Sergey Poznyakoff. Eclat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Eclat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eclat. If not, see . */ #include "eclat.h" static int isnumstr(const char *p) { for (; *p; p++) if (!isdigit(*p)) return 0; return 1; } void eclat_encode_devmap(struct ec2_request *q, struct grecs_list *list) { int i; char *bufptr = NULL; size_t bufsize = 0; struct grecs_list_entry *ep; if (!list) return; for (i = 1, ep = list->head; ep; ep = ep->next, i++) { char *dev = ep->data; char *p = strchr(dev, '='); if (!p) die(EX_USAGE, "malformed device mapping: %s", dev); *p++ = 0; grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d.DeviceName", i); eclat_request_add_param(q, bufptr, dev); if (strcmp(p, "none") == 0) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d.NoDevice", i); eclat_request_add_param(q, bufptr, NULL); } else if (strncmp(p, "ephemeral", 9) == 0) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d.VirtualName", i); eclat_request_add_param(q, bufptr, p); } else { struct wordsplit ws; /* [snapshot-id]:[volume-size]:[true|false]:[standard|io1[:iops]] */ ws.ws_delim = ":"; if (wordsplit(p, &ws, WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM)) die(EX_SOFTWARE, "failed to split string %s: %s", p, wordsplit_strerror(&ws)); if (ws.ws_wordc == 1) { if (isnumstr(ws.ws_wordv[0])) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d." "Ebs.VolumeSize", i); } else { translate_ids(1, &ws.ws_wordv[0], MAP_SNAPSHOT); if (strncmp(ws.ws_wordv[0], "snap-", 5) == 0) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d." "Ebs.SnapshotId", i); } else { die(EX_USAGE, "unrecognized word \"%s\", " "expected either a " "snapshot ID, " "or disk size, " "or a device-specification", ws.ws_wordv[0]); } } eclat_request_add_param(q, bufptr, ws.ws_wordv[0]); } else if (ws.ws_wordc < 2) { die(EX_USAGE, "not enough parts in device mapping \"%s\"", p); } else { if (ws.ws_wordv[0][0]) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d." "Ebs.SnapshotId", i); eclat_request_add_param(q, bufptr, ws.ws_wordv[0]); } if (ws.ws_wordv[1][0]) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d." "Ebs.VolumeSize", i); eclat_request_add_param(q, bufptr, ws.ws_wordv[1]); } } switch (ws.ws_wordc) { default: die(EX_USAGE, "too many parts in device mapping \"%s\"", p); case 5: if (ws.ws_wordv[4][0]) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d.Ebs.Iops", i); eclat_request_add_param(q, bufptr, ws.ws_wordv[4]); } /* fall through */ case 4: if (ws.ws_wordv[3][0]) { grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d.Ebs.VolumeType", i); eclat_request_add_param(q, bufptr, ws.ws_wordv[3]); } /* fall through */ case 3: if (ws.ws_wordv[2][0]) { if (strcmp(ws.ws_wordv[2], "false") && strcmp(ws.ws_wordv[2], "true")) die(EX_USAGE, "expected \"true\" or \"false\", " "but found \"%s\"", ws.ws_wordv[2]); grecs_asprintf(&bufptr, &bufsize, "BlockDeviceMapping.%d." "Ebs.DeleteOnTermination", i); eclat_request_add_param(q, bufptr, ws.ws_wordv[2]); } case 2: break; } wordsplit_free(&ws); } } free(bufptr); }