Revision c054b3fd qemu-img.c
b/qemu-img.c | ||
---|---|---|
21 | 21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 |
#include "qapi-visit.h" |
|
25 |
#include "qapi/qmp-output-visitor.h" |
|
26 |
#include "qjson.h" |
|
24 | 27 |
#include "qemu-common.h" |
25 | 28 |
#include "qemu-option.h" |
26 | 29 |
#include "qemu-error.h" |
27 | 30 |
#include "osdep.h" |
28 | 31 |
#include "sysemu.h" |
29 | 32 |
#include "block_int.h" |
33 |
#include <getopt.h> |
|
30 | 34 |
#include <stdio.h> |
31 | 35 |
|
32 | 36 |
#ifdef _WIN32 |
... | ... | |
84 | 88 |
" '-p' show progress of command (only certain commands)\n" |
85 | 89 |
" '-S' indicates the consecutive number of bytes that must contain only zeros\n" |
86 | 90 |
" for qemu-img to create a sparse image during conversion\n" |
91 |
" '--output' takes the format in which the output must be done (human or json)\n" |
|
87 | 92 |
"\n" |
88 | 93 |
"Parameters to check subcommand:\n" |
89 | 94 |
" '-r' tries to repair any inconsistencies that are found during the check.\n" |
... | ... | |
1102 | 1107 |
g_free(sn_tab); |
1103 | 1108 |
} |
1104 | 1109 |
|
1105 |
static int img_info(int argc, char **argv) |
|
1110 |
static void collect_snapshots(BlockDriverState *bs , ImageInfo *info) |
|
1111 |
{ |
|
1112 |
int i, sn_count; |
|
1113 |
QEMUSnapshotInfo *sn_tab = NULL; |
|
1114 |
SnapshotInfoList *info_list, *cur_item = NULL; |
|
1115 |
sn_count = bdrv_snapshot_list(bs, &sn_tab); |
|
1116 |
|
|
1117 |
for (i = 0; i < sn_count; i++) { |
|
1118 |
info->has_snapshots = true; |
|
1119 |
info_list = g_new0(SnapshotInfoList, 1); |
|
1120 |
|
|
1121 |
info_list->value = g_new0(SnapshotInfo, 1); |
|
1122 |
info_list->value->id = g_strdup(sn_tab[i].id_str); |
|
1123 |
info_list->value->name = g_strdup(sn_tab[i].name); |
|
1124 |
info_list->value->vm_state_size = sn_tab[i].vm_state_size; |
|
1125 |
info_list->value->date_sec = sn_tab[i].date_sec; |
|
1126 |
info_list->value->date_nsec = sn_tab[i].date_nsec; |
|
1127 |
info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; |
|
1128 |
info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; |
|
1129 |
|
|
1130 |
/* XXX: waiting for the qapi to support qemu-queue.h types */ |
|
1131 |
if (!cur_item) { |
|
1132 |
info->snapshots = cur_item = info_list; |
|
1133 |
} else { |
|
1134 |
cur_item->next = info_list; |
|
1135 |
cur_item = info_list; |
|
1136 |
} |
|
1137 |
|
|
1138 |
} |
|
1139 |
|
|
1140 |
g_free(sn_tab); |
|
1141 |
} |
|
1142 |
|
|
1143 |
static void dump_json_image_info(ImageInfo *info) |
|
1144 |
{ |
|
1145 |
Error *errp = NULL; |
|
1146 |
QString *str; |
|
1147 |
QmpOutputVisitor *ov = qmp_output_visitor_new(); |
|
1148 |
QObject *obj; |
|
1149 |
visit_type_ImageInfo(qmp_output_get_visitor(ov), |
|
1150 |
&info, NULL, &errp); |
|
1151 |
obj = qmp_output_get_qobject(ov); |
|
1152 |
str = qobject_to_json_pretty(obj); |
|
1153 |
assert(str != NULL); |
|
1154 |
printf("%s\n", qstring_get_str(str)); |
|
1155 |
qobject_decref(obj); |
|
1156 |
qmp_output_visitor_cleanup(ov); |
|
1157 |
QDECREF(str); |
|
1158 |
} |
|
1159 |
|
|
1160 |
static void collect_image_info(BlockDriverState *bs, |
|
1161 |
ImageInfo *info, |
|
1162 |
const char *filename, |
|
1163 |
const char *fmt) |
|
1106 | 1164 |
{ |
1107 |
int c; |
|
1108 |
const char *filename, *fmt; |
|
1109 |
BlockDriverState *bs; |
|
1110 |
char size_buf[128], dsize_buf[128]; |
|
1111 | 1165 |
uint64_t total_sectors; |
1112 |
int64_t allocated_size; |
|
1113 | 1166 |
char backing_filename[1024]; |
1114 | 1167 |
char backing_filename2[1024]; |
1115 | 1168 |
BlockDriverInfo bdi; |
1116 | 1169 |
|
1170 |
bdrv_get_geometry(bs, &total_sectors); |
|
1171 |
|
|
1172 |
info->filename = g_strdup(filename); |
|
1173 |
info->format = g_strdup(bdrv_get_format_name(bs)); |
|
1174 |
info->virtual_size = total_sectors * 512; |
|
1175 |
info->actual_size = bdrv_get_allocated_file_size(bs); |
|
1176 |
info->has_actual_size = info->actual_size >= 0; |
|
1177 |
if (bdrv_is_encrypted(bs)) { |
|
1178 |
info->encrypted = true; |
|
1179 |
info->has_encrypted = true; |
|
1180 |
} |
|
1181 |
if (bdrv_get_info(bs, &bdi) >= 0) { |
|
1182 |
if (bdi.cluster_size != 0) { |
|
1183 |
info->cluster_size = bdi.cluster_size; |
|
1184 |
info->has_cluster_size = true; |
|
1185 |
} |
|
1186 |
info->dirty_flag = bdi.is_dirty; |
|
1187 |
info->has_dirty_flag = true; |
|
1188 |
} |
|
1189 |
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); |
|
1190 |
if (backing_filename[0] != '\0') { |
|
1191 |
info->backing_filename = g_strdup(backing_filename); |
|
1192 |
info->has_backing_filename = true; |
|
1193 |
bdrv_get_full_backing_filename(bs, backing_filename2, |
|
1194 |
sizeof(backing_filename2)); |
|
1195 |
|
|
1196 |
if (strcmp(backing_filename, backing_filename2) != 0) { |
|
1197 |
info->full_backing_filename = |
|
1198 |
g_strdup(backing_filename2); |
|
1199 |
info->has_full_backing_filename = true; |
|
1200 |
} |
|
1201 |
|
|
1202 |
if (bs->backing_format[0]) { |
|
1203 |
info->backing_filename_format = g_strdup(bs->backing_format); |
|
1204 |
info->has_backing_filename_format = true; |
|
1205 |
} |
|
1206 |
} |
|
1207 |
} |
|
1208 |
|
|
1209 |
static void dump_human_image_info(ImageInfo *info) |
|
1210 |
{ |
|
1211 |
char size_buf[128], dsize_buf[128]; |
|
1212 |
if (!info->has_actual_size) { |
|
1213 |
snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); |
|
1214 |
} else { |
|
1215 |
get_human_readable_size(dsize_buf, sizeof(dsize_buf), |
|
1216 |
info->actual_size); |
|
1217 |
} |
|
1218 |
get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); |
|
1219 |
printf("image: %s\n" |
|
1220 |
"file format: %s\n" |
|
1221 |
"virtual size: %s (%" PRId64 " bytes)\n" |
|
1222 |
"disk size: %s\n", |
|
1223 |
info->filename, info->format, size_buf, |
|
1224 |
info->virtual_size, |
|
1225 |
dsize_buf); |
|
1226 |
|
|
1227 |
if (info->has_encrypted && info->encrypted) { |
|
1228 |
printf("encrypted: yes\n"); |
|
1229 |
} |
|
1230 |
|
|
1231 |
if (info->has_cluster_size) { |
|
1232 |
printf("cluster_size: %" PRId64 "\n", info->cluster_size); |
|
1233 |
} |
|
1234 |
|
|
1235 |
if (info->has_dirty_flag && info->dirty_flag) { |
|
1236 |
printf("cleanly shut down: no\n"); |
|
1237 |
} |
|
1238 |
|
|
1239 |
if (info->has_backing_filename) { |
|
1240 |
printf("backing file: %s", info->backing_filename); |
|
1241 |
if (info->has_full_backing_filename) { |
|
1242 |
printf(" (actual path: %s)", info->full_backing_filename); |
|
1243 |
} |
|
1244 |
putchar('\n'); |
|
1245 |
if (info->has_backing_filename_format) { |
|
1246 |
printf("backing file format: %s\n", info->backing_filename_format); |
|
1247 |
} |
|
1248 |
} |
|
1249 |
} |
|
1250 |
|
|
1251 |
enum {OPTION_OUTPUT = 256}; |
|
1252 |
|
|
1253 |
typedef enum OutputFormat { |
|
1254 |
OFORMAT_JSON, |
|
1255 |
OFORMAT_HUMAN, |
|
1256 |
} OutputFormat; |
|
1257 |
|
|
1258 |
static int img_info(int argc, char **argv) |
|
1259 |
{ |
|
1260 |
int c; |
|
1261 |
OutputFormat output_format = OFORMAT_HUMAN; |
|
1262 |
const char *filename, *fmt, *output; |
|
1263 |
BlockDriverState *bs; |
|
1264 |
ImageInfo *info; |
|
1265 |
|
|
1117 | 1266 |
fmt = NULL; |
1267 |
output = NULL; |
|
1118 | 1268 |
for(;;) { |
1119 |
c = getopt(argc, argv, "f:h"); |
|
1269 |
int option_index = 0; |
|
1270 |
static const struct option long_options[] = { |
|
1271 |
{"help", no_argument, 0, 'h'}, |
|
1272 |
{"format", required_argument, 0, 'f'}, |
|
1273 |
{"output", required_argument, 0, OPTION_OUTPUT}, |
|
1274 |
{0, 0, 0, 0} |
|
1275 |
}; |
|
1276 |
c = getopt_long(argc, argv, "f:h", |
|
1277 |
long_options, &option_index); |
|
1120 | 1278 |
if (c == -1) { |
1121 | 1279 |
break; |
1122 | 1280 |
} |
... | ... | |
1128 | 1286 |
case 'f': |
1129 | 1287 |
fmt = optarg; |
1130 | 1288 |
break; |
1289 |
case OPTION_OUTPUT: |
|
1290 |
output = optarg; |
|
1291 |
break; |
|
1131 | 1292 |
} |
1132 | 1293 |
} |
1133 | 1294 |
if (optind >= argc) { |
... | ... | |
1135 | 1296 |
} |
1136 | 1297 |
filename = argv[optind++]; |
1137 | 1298 |
|
1299 |
if (output && !strcmp(output, "json")) { |
|
1300 |
output_format = OFORMAT_JSON; |
|
1301 |
} else if (output && !strcmp(output, "human")) { |
|
1302 |
output_format = OFORMAT_HUMAN; |
|
1303 |
} else if (output) { |
|
1304 |
error_report("--output must be used with human or json as argument."); |
|
1305 |
return 1; |
|
1306 |
} |
|
1307 |
|
|
1138 | 1308 |
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING); |
1139 | 1309 |
if (!bs) { |
1140 | 1310 |
return 1; |
1141 | 1311 |
} |
1142 |
bdrv_get_geometry(bs, &total_sectors); |
|
1143 |
get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512); |
|
1144 |
allocated_size = bdrv_get_allocated_file_size(bs); |
|
1145 |
if (allocated_size < 0) { |
|
1146 |
snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); |
|
1147 |
} else { |
|
1148 |
get_human_readable_size(dsize_buf, sizeof(dsize_buf), |
|
1149 |
allocated_size); |
|
1150 |
} |
|
1151 |
printf("image: %s\n" |
|
1152 |
"file format: %s\n" |
|
1153 |
"virtual size: %s (%" PRId64 " bytes)\n" |
|
1154 |
"disk size: %s\n", |
|
1155 |
filename, bdrv_get_format_name(bs), size_buf, |
|
1156 |
(total_sectors * 512), |
|
1157 |
dsize_buf); |
|
1158 |
if (bdrv_is_encrypted(bs)) { |
|
1159 |
printf("encrypted: yes\n"); |
|
1160 |
} |
|
1161 |
if (bdrv_get_info(bs, &bdi) >= 0) { |
|
1162 |
if (bdi.cluster_size != 0) { |
|
1163 |
printf("cluster_size: %d\n", bdi.cluster_size); |
|
1164 |
} |
|
1165 |
if (bdi.is_dirty) { |
|
1166 |
printf("cleanly shut down: no\n"); |
|
1167 |
} |
|
1168 |
} |
|
1169 |
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); |
|
1170 |
if (backing_filename[0] != '\0') { |
|
1171 |
bdrv_get_full_backing_filename(bs, backing_filename2, |
|
1172 |
sizeof(backing_filename2)); |
|
1173 |
printf("backing file: %s", backing_filename); |
|
1174 |
if (strcmp(backing_filename, backing_filename2) != 0) { |
|
1175 |
printf(" (actual path: %s)", backing_filename2); |
|
1176 |
} |
|
1177 |
putchar('\n'); |
|
1312 |
|
|
1313 |
info = g_new0(ImageInfo, 1); |
|
1314 |
collect_image_info(bs, info, filename, fmt); |
|
1315 |
|
|
1316 |
switch (output_format) { |
|
1317 |
case OFORMAT_HUMAN: |
|
1318 |
dump_human_image_info(info); |
|
1319 |
dump_snapshots(bs); |
|
1320 |
break; |
|
1321 |
case OFORMAT_JSON: |
|
1322 |
collect_snapshots(bs, info); |
|
1323 |
dump_json_image_info(info); |
|
1324 |
break; |
|
1178 | 1325 |
} |
1179 |
dump_snapshots(bs); |
|
1326 |
|
|
1327 |
qapi_free_ImageInfo(info); |
|
1180 | 1328 |
bdrv_delete(bs); |
1181 | 1329 |
return 0; |
1182 | 1330 |
} |
Also available in: Unified diff