LCOV - code coverage report
Current view: top level - drivers - td.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 245 0.0 %
Date: 2025-03-07 10:41:45 Functions: 0 10 0.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2016, Citrix Systems, Inc.
       3                 :            :  *
       4                 :            :  * All rights reserved.
       5                 :            :  *
       6                 :            :  * Redistribution and use in source and binary forms, with or without
       7                 :            :  * modification, are permitted provided that the following conditions are met:
       8                 :            :  * 
       9                 :            :  *  1. Redistributions of source code must retain the above copyright
      10                 :            :  *     notice, this list of conditions and the following disclaimer.
      11                 :            :  *  2. Redistributions in binary form must reproduce the above copyright
      12                 :            :  *     notice, this list of conditions and the following disclaimer in the
      13                 :            :  *     documentation and/or other materials provided with the distribution.
      14                 :            :  *  3. Neither the name of the copyright holder nor the names of its 
      15                 :            :  *     contributors may be used to endorse or promote products derived from 
      16                 :            :  *     this software without specific prior written permission.
      17                 :            :  *
      18                 :            :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19                 :            :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20                 :            :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      21                 :            :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
      22                 :            :  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      23                 :            :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      24                 :            :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      25                 :            :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      26                 :            :  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      27                 :            :  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      28                 :            :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 :            :  */
      30                 :            : 
      31                 :            : #ifdef HAVE_CONFIG_H
      32                 :            : #include "config.h"
      33                 :            : #endif
      34                 :            : 
      35                 :            : #include <errno.h>
      36                 :            : #include <fcntl.h>
      37                 :            : #include <stdio.h>
      38                 :            : #include <stdlib.h>
      39                 :            : #include <sys/types.h>
      40                 :            : #include <sys/stat.h>
      41                 :            : #include <sys/resource.h>
      42                 :            : #include <unistd.h>
      43                 :            : #include <string.h>
      44                 :            : 
      45                 :            : #include "libvhd.h"
      46                 :            : #include "vhd-util.h"
      47                 :            : #include "tapdisk-utils.h"
      48                 :            : 
      49                 :            : #if 1
      50                 :            : #define DFPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a )
      51                 :            : #else
      52                 :            : #define DFPRINTF(_f, _a...) ((void)0)
      53                 :            : #endif
      54                 :            : 
      55                 :            : typedef enum {
      56                 :            :         TD_FIELD_HIDDEN  = 0,
      57                 :            :         TD_FIELD_INVALID = 1
      58                 :            : } td_field_t;
      59                 :            : 
      60                 :            : struct vdi_field {
      61                 :            :         char       *name;
      62                 :            :         td_field_t  id;
      63                 :            : };
      64                 :            : 
      65                 :            : static struct vdi_field td_vdi_fields[TD_FIELD_INVALID] = {
      66                 :            :         { .id = TD_FIELD_HIDDEN, .name = "hidden" }
      67                 :            : };
      68                 :            : 
      69                 :            : typedef enum {
      70                 :            :         TD_CMD_CREATE    = 0,
      71                 :            :         TD_CMD_SNAPSHOT,
      72                 :            : /*      TD_CMD_COALESCE,       */
      73                 :            :         TD_CMD_QUERY,
      74                 :            : /*      TD_CMD_RESIZE,         */
      75                 :            :         TD_CMD_SET,
      76                 :            : /*      TD_CMD_REPAIR,         */
      77                 :            : /*      TD_CMD_FILL,           */
      78                 :            : /*      TD_CMD_READ,           */
      79                 :            :         TD_CMD_INVALID,
      80                 :            : } td_command_t;
      81                 :            : 
      82                 :            : struct command {
      83                 :            :         td_command_t  id;
      84                 :            :         char         *name;
      85                 :            :         int           needs_type;
      86                 :            : };
      87                 :            : 
      88                 :            : struct command commands[TD_CMD_INVALID] = {
      89                 :            :         { .id = TD_CMD_CREATE,   .name = "create",   .needs_type = 1 },
      90                 :            :         { .id = TD_CMD_SNAPSHOT, .name = "snapshot", .needs_type = 1 },
      91                 :            : /*      { .id = TD_CMD_COALESCE, .name = "coalesce", .needs_type = 1 },    */
      92                 :            :         { .id = TD_CMD_QUERY,    .name = "query",    .needs_type = 1 },
      93                 :            : /*      { .id = TD_CMD_RESIZE,   .name = "resize",   .needs_type = 1 },    */
      94                 :            :         { .id = TD_CMD_SET,      .name = "set",      .needs_type = 1 },
      95                 :            : /*      { .id = TD_CMD_REPAIR,   .name = "repair",   .needs_type = 1 },    */
      96                 :            : /*      { .id = TD_CMD_FILL,     .name = "fill",     .needs_type = 1 },    */
      97                 :            : /*      { .id = TD_CMD_READ,     .name = "read",     .needs_type = 1 },    */
      98                 :            : };
      99                 :            : 
     100                 :            : typedef enum {
     101                 :            :         TD_TYPE_VHD         = 0,
     102                 :            :         TD_TYPE_AIO,
     103                 :            :         TD_TYPE_INVALID,
     104                 :            : } td_disk_t;
     105                 :            : 
     106                 :            : const char *td_disk_types[TD_TYPE_INVALID] = {
     107                 :            :         "vhd",
     108                 :            :         "aio",
     109                 :            : };
     110                 :            : 
     111                 :            : #define print_commands()                                                \
     112                 :            :         do {                                                            \
     113                 :            :                 int i;                                                  \
     114                 :            :                 fprintf(stderr, "COMMAND := { ");                     \
     115                 :            :                 fprintf(stderr, "%s", commands[0].name);              \
     116                 :            :                 for (i = 1; i < TD_CMD_INVALID; i++)                 \
     117                 :            :                         fprintf(stderr, " | %s", commands[i].name);   \
     118                 :            :                 fprintf(stderr, " }\n");                              \
     119                 :            :         } while (0)
     120                 :            : 
     121                 :            : #define print_disk_types()                                              \
     122                 :            :         do {                                                            \
     123                 :            :                 int i;                                                  \
     124                 :            :                 fprintf(stderr, "TYPE := { ");                                \
     125                 :            :                 fprintf(stderr, "%s", td_disk_types[0]);              \
     126                 :            :                 for (i = 1; i < TD_TYPE_INVALID; i++)                        \
     127                 :            :                         fprintf(stderr, " | %s", td_disk_types[i]);   \
     128                 :            :                 fprintf(stderr, " }\n");                              \
     129                 :            :         } while (0);
     130                 :            : 
     131                 :            : #define print_field_names()                                             \
     132                 :            :         do {                                                            \
     133                 :            :                 int i;                                                  \
     134                 :            :                 fprintf(stderr, "FIELD := { ");                               \
     135                 :            :                 fprintf(stderr, "%s", td_vdi_fields[0].name);         \
     136                 :            :                 for (i = 1; i < TD_FIELD_INVALID; i++)                       \
     137                 :            :                         fprintf(stderr, " | %s", td_vdi_fields[i].name); \
     138                 :            :                 fprintf(stderr, " }\n");                              \
     139                 :            :         } while (0)
     140                 :            : 
     141                 :            : void 
     142                 :          0 : help(void)
     143                 :            : {
     144                 :          0 :         fprintf(stderr, "Tapdisk Utilities: v1.0.0\n");
     145                 :          0 :         fprintf(stderr, "usage: td-util COMMAND [TYPE] [OPTIONS]\n");
     146                 :          0 :         print_commands();
     147                 :          0 :         print_disk_types();
     148                 :          0 :         exit(-1);
     149                 :            : }
     150                 :            : 
     151                 :            : struct command *
     152                 :          0 : get_command(char *command)
     153                 :            : {
     154                 :            :         int i;
     155                 :            : 
     156                 :          0 :         for (i = 0; i < TD_CMD_INVALID; i++)
     157                 :          0 :                 if (!strcmp(command, commands[i].name))
     158                 :          0 :                         return &commands[i];
     159                 :            : 
     160                 :            :         return NULL;
     161                 :            : }
     162                 :            : 
     163                 :            : struct vdi_field *
     164                 :          0 : get_field(char *field)
     165                 :            : {
     166                 :            :         int i;
     167                 :            : 
     168                 :          0 :         for (i = 0; i < TD_FIELD_INVALID; i++)
     169                 :          0 :                 if (!strcmp(field, td_vdi_fields[i].name))
     170                 :          0 :                         return &td_vdi_fields[i];
     171                 :            : 
     172                 :            :         return NULL;
     173                 :            : }
     174                 :            : 
     175                 :            : int
     176                 :          0 : get_driver_type(char *type)
     177                 :            : {
     178                 :            :         int i;
     179                 :            : 
     180                 :          0 :         if (strnlen(type, 25) >= 25)
     181                 :            :                 return -ENAMETOOLONG;
     182                 :            : 
     183                 :          0 :         for (i = 0; i < TD_TYPE_INVALID; i++)
     184                 :          0 :                 if (!strcmp(type, td_disk_types[i]))
     185                 :            :                         return i;
     186                 :            : 
     187                 :            :         return -TD_TYPE_INVALID;
     188                 :            : }
     189                 :            : 
     190                 :            : int
     191                 :          0 : td_create(int type, int argc, char *argv[])
     192                 :            : {
     193                 :            :         ssize_t mb;
     194                 :            :         uint64_t size;
     195                 :            :         char *name, *buf;
     196                 :          0 :         int c, i, fd, sparse = 1, fixedsize = 0;
     197                 :            : 
     198                 :          0 :         while ((c = getopt(argc, argv, "hrb")) != -1) {
     199                 :          0 :                 switch(c) {
     200                 :            :                 case 'r':
     201                 :            :                         sparse = 0;
     202                 :            :                         break;
     203                 :            :                 case 'b':
     204                 :          0 :                         fixedsize = 1;
     205                 :          0 :                         break;
     206                 :            :                 default:
     207                 :          0 :                         fprintf(stderr, "Unknown option %c\n", (char)c);
     208                 :            :                 case 'h':
     209                 :            :                         goto usage;
     210                 :            :                 }
     211                 :            :         }
     212                 :            : 
     213                 :          0 :         if (optind != (argc - 2))
     214                 :            :                 goto usage;
     215                 :            : 
     216                 :          0 :         mb   = 1 << 20;
     217                 :          0 :         size = atoi(argv[optind++]);
     218                 :          0 :         size = size << 20;
     219                 :          0 :         name = argv[optind];
     220                 :            : 
     221                 :          0 :         if (strnlen(name, MAX_NAME_LEN) == MAX_NAME_LEN) {
     222                 :          0 :                 fprintf(stderr, "Device name too long\n");
     223                 :          0 :                 return ENAMETOOLONG;
     224                 :            :         }
     225                 :            : 
     226                 :          0 :         if (type == TD_TYPE_VHD) {
     227                 :          0 :                 int cargc = 0;
     228                 :            :                 char sbuf[32], *cargv[10];
     229                 :            : 
     230                 :          0 :                 size >>= 20;
     231                 :            : 
     232                 :            :                 memset(cargv, 0, sizeof(cargv));
     233                 :            :                 snprintf(sbuf, sizeof(sbuf) - 1, "%"PRIu64, size);
     234                 :          0 :                 cargv[cargc++] = "create";
     235                 :          0 :                 cargv[cargc++] = "-n";
     236                 :          0 :                 cargv[cargc++] = name;
     237                 :          0 :                 cargv[cargc++] = "-s";
     238                 :          0 :                 cargv[cargc++] = sbuf;
     239                 :          0 :                 if (!sparse)
     240                 :          0 :                         cargv[cargc++] = "-r";
     241                 :          0 :                 if (fixedsize)
     242                 :          0 :                         cargv[cargc++] = "-b";
     243                 :            : 
     244                 :          0 :                 return vhd_util_create(cargc, cargv);
     245                 :            :         }
     246                 :            : 
     247                 :            :         /* generic create */
     248                 :          0 :         if (sparse) {
     249                 :          0 :                 fprintf(stderr, "Cannot create sparse %s image\n",
     250                 :            :                         td_disk_types[type]);
     251                 :          0 :                 return EINVAL;
     252                 :            :         }
     253                 :            : 
     254                 :          0 :         buf = calloc(1, mb);
     255                 :          0 :         if (!buf)
     256                 :            :                 return ENOMEM;
     257                 :            : 
     258                 :          0 :         fd = open(name, O_WRONLY | O_DIRECT | O_CREAT | O_TRUNC, 0644);
     259                 :          0 :         if (fd == -1) {
     260                 :          0 :                 free(buf);
     261                 :          0 :                 return errno;
     262                 :            :         }
     263                 :            : 
     264                 :          0 :         size >>= 20;
     265                 :          0 :         for (i = 0; i < size; i++)
     266                 :          0 :                 if (write(fd, buf, mb) != mb) {
     267                 :          0 :                         close(fd);
     268                 :          0 :                         unlink(name);
     269                 :          0 :                         free(buf);
     270                 :          0 :                         return EIO;
     271                 :            :                 }
     272                 :            : 
     273                 :          0 :         close(fd);
     274                 :          0 :         free(buf);
     275                 :          0 :         return 0;
     276                 :            : 
     277                 :            :  usage:
     278                 :          0 :         fprintf(stderr, "usage: td-util create %s [-h help] [-r reserve] "
     279                 :            :                 "[-b file_is_fixed_size] <SIZE(MB)> <FILENAME>\n",
     280                 :            :                 td_disk_types[type]);
     281                 :          0 :         return EINVAL;
     282                 :            : }
     283                 :            : 
     284                 :            : int
     285                 :          0 : td_snapshot(int type, int argc, char *argv[])
     286                 :            : {
     287                 :            :         char *cargv[10];
     288                 :            :         int c, err, cargc;
     289                 :            :         struct stat stats;
     290                 :          0 :         char *name, *backing, *limit = NULL;
     291                 :          0 :         int fixedsize = 0, rawparent = 0;
     292                 :            : 
     293                 :          0 :         if (type != TD_TYPE_VHD) {
     294                 :          0 :                 fprintf(stderr, "Cannot create snapshot of %s image type\n",
     295                 :            :                         td_disk_types[type]);
     296                 :          0 :                 return EINVAL;
     297                 :            :         }
     298                 :            : 
     299                 :          0 :         while ((c = getopt(argc, argv, "hbml:")) != -1) {
     300                 :          0 :                 switch(c) {
     301                 :            :                 case 'b':
     302                 :            :                         fixedsize = 1;
     303                 :            :                         break;
     304                 :            :                 case 'm':
     305                 :          0 :                         rawparent = 1;
     306                 :          0 :                         break;
     307                 :            :                 case 'l':
     308                 :          0 :                         limit = optarg;
     309                 :          0 :                         break;
     310                 :            :                 case 'h':
     311                 :            :                         err = 0;
     312                 :            :                         goto usage;
     313                 :            :                 default:
     314                 :          0 :                         err = EINVAL;
     315                 :          0 :                         goto usage;
     316                 :            :                 }
     317                 :            :         }
     318                 :            : 
     319                 :          0 :         if (optind != (argc - 2)) {
     320                 :            :                 err = EINVAL;
     321                 :            :                 goto usage;
     322                 :            :         }
     323                 :            : 
     324                 :          0 :         name    = argv[optind++];
     325                 :          0 :         backing = argv[optind++];
     326                 :            : 
     327                 :          0 :         if (strnlen(name, MAX_NAME_LEN) == MAX_NAME_LEN ||
     328                 :          0 :             strnlen(backing, MAX_NAME_LEN) == MAX_NAME_LEN) {
     329                 :          0 :                 fprintf(stderr, "Device name too long\n");
     330                 :            :                 return ENAMETOOLONG;
     331                 :            :         }
     332                 :            : 
     333                 :          0 :         if (stat(backing, &stats) == -1) {
     334                 :          0 :                 fprintf(stderr, "File %s not found\n", backing);
     335                 :          0 :                 return errno;
     336                 :            :         }
     337                 :            : 
     338                 :          0 :         cargc = 0;
     339                 :            :         memset(cargv, 0, sizeof(cargv));
     340                 :          0 :         cargv[cargc++] = "snapshot";
     341                 :          0 :         cargv[cargc++] = "-n";
     342                 :          0 :         cargv[cargc++] = name;
     343                 :          0 :         cargv[cargc++] = "-p";
     344                 :          0 :         cargv[cargc++] = backing;
     345                 :          0 :         if (fixedsize)
     346                 :          0 :                 cargv[cargc++] = "-b";
     347                 :          0 :         if (rawparent)
     348                 :          0 :                 cargv[cargc++] = "-m";
     349                 :          0 :         if (limit) {
     350                 :          0 :                 cargv[cargc++] = "-l";
     351                 :          0 :                 cargv[cargc++] = limit;
     352                 :            :         }
     353                 :          0 :         return vhd_util_snapshot(cargc, cargv);
     354                 :            : 
     355                 :            :  usage:
     356                 :          0 :         fprintf(stderr, "usage: td-util snapshot %s [-h help] [-m parent_raw] "
     357                 :            :                 "[-b file_is_fixed_size] [-l snapshot depth limit] "
     358                 :            :                 "<FILENAME> <BACKING_FILENAME>\n", td_disk_types[type]);
     359                 :            :         return err;
     360                 :            : }
     361                 :            : 
     362                 :            : int
     363                 :          0 : td_coalesce(int type, int argc, char *argv[])
     364                 :            : {
     365                 :            :         int c, ret, cargc;
     366                 :            :         char *name, *cargv[3];
     367                 :            : 
     368                 :          0 :         if (type != TD_TYPE_VHD) {
     369                 :          0 :                 fprintf(stderr, "Cannot create snapshot of %s image type\n",
     370                 :            :                         td_disk_types[type]);
     371                 :          0 :                 return EINVAL;
     372                 :            :         }
     373                 :            : 
     374                 :          0 :         while ((c = getopt(argc, argv, "h")) != -1) {
     375                 :          0 :                 switch(c) {
     376                 :            :                 default:
     377                 :          0 :                         fprintf(stderr, "Unknown option %c\n", (char)c);
     378                 :            :                 case 'h':
     379                 :            :                         goto usage;
     380                 :            :                 }
     381                 :            :         }
     382                 :            : 
     383                 :          0 :         if (optind != (argc - 1))
     384                 :            :                 goto usage;
     385                 :            : 
     386                 :          0 :         name = argv[optind++];
     387                 :            : 
     388                 :          0 :         if (strnlen(name, MAX_NAME_LEN) == MAX_NAME_LEN) {
     389                 :          0 :                 fprintf(stderr, "Device name too long\n");
     390                 :            :                 return ENAMETOOLONG;
     391                 :            :         }
     392                 :            : 
     393                 :          0 :         cargc = 0;
     394                 :            :         memset(cargv, 0, sizeof(cargv));
     395                 :          0 :         cargv[cargc++] = "coalesce";
     396                 :          0 :         cargv[cargc++] = "-n";
     397                 :          0 :         cargv[cargc++] = name;
     398                 :          0 :         ret = vhd_util_coalesce(cargc, cargv);
     399                 :          0 :         if (ret)
     400                 :            :                 printf("coalesce failed: %d\n", ret);
     401                 :            : 
     402                 :          0 :         return ret;
     403                 :            : 
     404                 :            :  usage:
     405                 :          0 :         fprintf(stderr, "usage: td-util coalesce %s [-h help] "
     406                 :            :                 "<FILENAME>\n", td_disk_types[type]);
     407                 :            :         return EINVAL;
     408                 :            : }
     409                 :            : 
     410                 :            : int
     411                 :          0 : td_query(int type, int argc, char *argv[])
     412                 :            : {
     413                 :            :         char *name;
     414                 :          0 :         int c, size = 0, parent = 0, fields = 0, depth = 0, err = 0;
     415                 :          0 :         int flags = VHD_OPEN_RDONLY;
     416                 :            : 
     417                 :          0 :         while ((c = getopt(argc, argv, "hvpfdb")) != -1) {
     418                 :          0 :                 switch(c) {
     419                 :            :                 case 'v':
     420                 :            :                         size = 1;
     421                 :            :                         break;
     422                 :            :                 case 'p':
     423                 :          0 :                         parent = 1;
     424                 :          0 :                         break;
     425                 :            :                 case 'f':
     426                 :          0 :                         fields = 1;
     427                 :          0 :                         break;
     428                 :            :                 case 'd':
     429                 :          0 :                         depth = 1;
     430                 :          0 :                         break;
     431                 :            :                 case 'h':
     432                 :            :                         err = 0;
     433                 :            :                         goto usage;
     434                 :            :                 case 'b':
     435                 :          0 :                         flags |= VHD_OPEN_USE_BKP_FOOTER;
     436                 :          0 :                         break;
     437                 :            :                 default:
     438                 :          0 :                         err = EINVAL;
     439                 :          0 :                         goto usage;
     440                 :            :                 }
     441                 :            :         }
     442                 :            : 
     443                 :          0 :         if (optind != (argc - 1)) {
     444                 :            :                 err = EINVAL;
     445                 :            :                 goto usage;
     446                 :            :         }
     447                 :            : 
     448                 :          0 :         name = argv[optind++];
     449                 :            : 
     450                 :          0 :         if (strnlen(name, MAX_NAME_LEN) == MAX_NAME_LEN) {
     451                 :          0 :                 fprintf(stderr, "Device name too long\n");
     452                 :          0 :                 return ENAMETOOLONG;
     453                 :            :         }
     454                 :            : 
     455                 :          0 :         if (type == TD_TYPE_VHD) {
     456                 :            :                 vhd_context_t vhd;
     457                 :            : 
     458                 :          0 :                 err = vhd_open(&vhd, name, flags);
     459                 :          0 :                 if (err) {
     460                 :            :                         printf("failed opening %s: %d\n", name, err);
     461                 :          0 :                         return err;
     462                 :            :                 }
     463                 :            : 
     464                 :          0 :                 if (size)
     465                 :          0 :                         printf("%"PRIu64"\n", vhd.footer.curr_size >> 20);
     466                 :            : 
     467                 :          0 :                 if (parent) {
     468                 :          0 :                         if (vhd.footer.type != HD_TYPE_DIFF)
     469                 :            :                                 printf("%s has no parent\n", name);
     470                 :            :                         else {
     471                 :            :                                 char *pname;
     472                 :            : 
     473                 :          0 :                                 err = vhd_parent_locator_get(&vhd, &pname);
     474                 :          0 :                                 if (err)
     475                 :            :                                         printf("failed getting parent: %d\n",
     476                 :            :                                                err);
     477                 :            :                                 else {
     478                 :          0 :                                         printf("%s\n", pname);
     479                 :          0 :                                         free(pname);
     480                 :            :                                 }
     481                 :            :                         }
     482                 :            :                 }
     483                 :            : 
     484                 :          0 :                 if (fields) {
     485                 :            :                         int ret, hidden;
     486                 :            : 
     487                 :          0 :                         ret = vhd_hidden(&vhd, &hidden);
     488                 :          0 :                         if (ret) {
     489                 :            :                                 printf("failed checking 'hidden' field: %d\n",
     490                 :            :                                        ret);
     491                 :          0 :                                 err = (err ? : ret);
     492                 :            :                         } else
     493                 :          0 :                                 printf("%s: %d\n",
     494                 :            :                                        td_vdi_fields[TD_FIELD_HIDDEN].name,
     495                 :            :                                        hidden);
     496                 :            :                 }
     497                 :            : 
     498                 :          0 :                 if (depth) {
     499                 :            :                         int ret, length;
     500                 :            : 
     501                 :          0 :                         ret = vhd_chain_depth(&vhd, &length);
     502                 :          0 :                         if (ret)
     503                 :            :                                 printf("error checking chain depth: %d\n", ret);
     504                 :            :                         else
     505                 :          0 :                                 printf("chain depth: %d\n", length);
     506                 :            : 
     507                 :          0 :                         err = (err ? : ret);
     508                 :            :                 }
     509                 :            : 
     510                 :          0 :                 vhd_close(&vhd);
     511                 :            : 
     512                 :          0 :         } else if (type == TD_TYPE_AIO) {
     513                 :          0 :                 if (size) {
     514                 :            :                         int fd;
     515                 :            :                         uint64_t secs;
     516                 :            :                         uint32_t ssize;
     517                 :            : 
     518                 :          0 :                         fd = open(name, O_RDONLY | O_LARGEFILE);
     519                 :          0 :                         if (fd == -1) {
     520                 :          0 :                                 printf("failed opening %s: %d\n", name, errno);
     521                 :          0 :                                 return -errno;
     522                 :            :                         }
     523                 :            : 
     524                 :          0 :                         err = tapdisk_get_image_size(fd, &secs, &ssize);
     525                 :          0 :                         close(fd);
     526                 :            : 
     527                 :          0 :                         if (err) {
     528                 :            :                                 printf("failed getting size for %s: %d\n:",
     529                 :            :                                        name, err);
     530                 :            :                                 return err;
     531                 :            :                         }
     532                 :            : 
     533                 :          0 :                         printf("%"PRIu64"\n", secs >> 11);
     534                 :            :                 }
     535                 :            : 
     536                 :          0 :                 if (parent)
     537                 :            :                         printf("%s has no parent\n", name);
     538                 :            : 
     539                 :          0 :                 if (fields) {
     540                 :            :                         int i;
     541                 :            : 
     542                 :          0 :                         for (i = 0; i < TD_FIELD_INVALID; i++)
     543                 :          0 :                                 printf("%s: 0\n", td_vdi_fields[i].name);
     544                 :            :                 }
     545                 :            :         }
     546                 :            : 
     547                 :          0 :         return err;
     548                 :            : 
     549                 :            :  usage:
     550                 :          0 :         fprintf(stderr, "usage: td-util query %s [-h help] [-v virtsize] "
     551                 :            :                 "[-p parent] [-f fields] [-b don't trust the footer, use the back-up "
     552                 :            :                 "one instead] <FILENAME>\n", td_disk_types[type]);
     553                 :          0 :         return err;
     554                 :            : }
     555                 :            : 
     556                 :            : int
     557                 :          0 : td_set_field(int type, int argc, char *argv[])
     558                 :            : {
     559                 :            :         int c, cargc;
     560                 :            :         struct vdi_field *field;
     561                 :            :         char *name, *value, *cargv[7];
     562                 :            : 
     563                 :          0 :         if (type != TD_TYPE_VHD) {
     564                 :          0 :                 fprintf(stderr, "Cannot set fields of %s images\n",
     565                 :            :                         td_disk_types[type]);
     566                 :          0 :                 return EINVAL;
     567                 :            :         }
     568                 :            : 
     569                 :          0 :         while ((c = getopt(argc, argv, "h")) != -1) {
     570                 :          0 :                 switch(c) {
     571                 :            :                 default:
     572                 :          0 :                         fprintf(stderr, "Unknown option %c\n", (char)c);
     573                 :            :                 case 'h':
     574                 :            :                         goto usage;
     575                 :            :                 }
     576                 :            :         }
     577                 :            : 
     578                 :          0 :         if (optind != (argc - 3))
     579                 :            :                 goto usage;
     580                 :            : 
     581                 :          0 :         name  = argv[optind++];
     582                 :            : 
     583                 :          0 :         field = get_field(argv[optind]);
     584                 :          0 :         if (!field || field->id != TD_FIELD_HIDDEN) {
     585                 :          0 :                 fprintf(stderr, "Invalid field %s\n", argv[optind]);
     586                 :            :                 goto usage;
     587                 :            :         }
     588                 :            : 
     589                 :          0 :         value = argv[++optind];
     590                 :            : 
     591                 :          0 :         cargc = 0;
     592                 :            :         memset(cargv, 0, sizeof(cargv));
     593                 :          0 :         cargv[cargc++] = "set";
     594                 :          0 :         cargv[cargc++] = "-n";
     595                 :          0 :         cargv[cargc++] = name;
     596                 :          0 :         cargv[cargc++] = "-f";
     597                 :          0 :         cargv[cargc++] = field->name;
     598                 :          0 :         cargv[cargc++] = "-v";
     599                 :          0 :         cargv[cargc++] = value;
     600                 :          0 :         return vhd_util_set_field(cargc, cargv);
     601                 :            : 
     602                 :            :  usage:
     603                 :          0 :         fprintf(stderr, "usage: td-util set %s [-h help] "
     604                 :            :                 "<FILENAME> <FIELD> <VALUE>\n", td_disk_types[type]);
     605                 :          0 :         print_field_names();
     606                 :            :         return EINVAL;
     607                 :            : }
     608                 :            : 
     609                 :            : int
     610                 :          0 : main(int argc, char *argv[])
     611                 :            : {
     612                 :            :         char **cargv;
     613                 :            :         struct command *cmd;
     614                 :          0 :         int cargc, i, type = -1, ret = 0;
     615                 :            : 
     616                 :            : #ifdef CORE_DUMP
     617                 :            :         struct rlimit rlim;
     618                 :            :         rlim.rlim_cur = RLIM_INFINITY;
     619                 :            :         rlim.rlim_max = RLIM_INFINITY;
     620                 :            :         if (setrlimit(RLIMIT_CORE, &rlim) < 0)
     621                 :            :                 fprintf(stderr, "setrlimit failed: %d\n", errno);
     622                 :            : #endif
     623                 :            : 
     624                 :          0 :         if (argc < 2)
     625                 :          0 :                 help();
     626                 :            : 
     627                 :          0 :         cargc = argc - 1;
     628                 :          0 :         cmd   = get_command(argv[1]);
     629                 :          0 :         if (!cmd) {
     630                 :          0 :                 fprintf(stderr, "invalid COMMAND %s\n", argv[1]);
     631                 :          0 :                 help();
     632                 :            :         }
     633                 :            : 
     634                 :          0 :         if (cmd->needs_type) {
     635                 :          0 :                 if (argc < 3) {
     636                 :          0 :                         fprintf(stderr, "td-util %s requires a TYPE\n",
     637                 :            :                                 cmd->name);
     638                 :          0 :                         print_disk_types();
     639                 :          0 :                         exit(-1);
     640                 :            :                 }
     641                 :            : 
     642                 :          0 :                 type = get_driver_type(argv[2]);
     643                 :          0 :                 if (type < 0) {
     644                 :          0 :                         fprintf(stderr, "invalid TYPE '%s'.\n", argv[2]);
     645                 :          0 :                         print_disk_types();
     646                 :          0 :                         exit(-1);
     647                 :            :                 }
     648                 :          0 :                 --cargc;
     649                 :            :         }
     650                 :            : 
     651                 :          0 :         cargv = malloc(sizeof(char *) * cargc);
     652                 :          0 :         if (!cargv)
     653                 :          0 :                 exit(ENOMEM);
     654                 :            : 
     655                 :          0 :         cargv[0] = cmd->name;
     656                 :          0 :         for (i = 1; i < cargc; i++)
     657                 :          0 :                 cargv[i] = argv[i + (argc - cargc)];
     658                 :            : 
     659                 :          0 :         switch(cmd->id) {
     660                 :            :         case TD_CMD_CREATE:
     661                 :          0 :                 ret = td_create(type, cargc, cargv);
     662                 :          0 :                 break;
     663                 :            :         case TD_CMD_SNAPSHOT:
     664                 :          0 :                 ret = td_snapshot(type, cargc, cargv);
     665                 :          0 :                 break;
     666                 :            : /*
     667                 :            :         case TD_CMD_COALESCE:
     668                 :            :                 ret = td_coalesce(type, cargc, cargv);
     669                 :            :                 break;
     670                 :            : */
     671                 :            :         case TD_CMD_QUERY:
     672                 :          0 :                 ret = td_query(type, cargc, cargv);
     673                 :          0 :                 break;
     674                 :            : /*
     675                 :            :         case TD_CMD_RESIZE:
     676                 :            :                 ret = td_resize(type, cargc, cargv);
     677                 :            :                 break;
     678                 :            : */
     679                 :            :         case TD_CMD_SET:
     680                 :          0 :                 ret = td_set_field(type, cargc, cargv);
     681                 :          0 :                 break;
     682                 :            : /*
     683                 :            :         case TD_CMD_REPAIR:
     684                 :            :                 ret = td_repair(type, cargc, cargv);
     685                 :            :                 break;
     686                 :            :         case TD_CMD_FILL:
     687                 :            :                 ret = td_fill(type, cargc, cargv);
     688                 :            :                 break;
     689                 :            :         case TD_CMD_READ:
     690                 :            :                 ret = td_read(type, cargc, cargv);
     691                 :            :                 break;
     692                 :            : */
     693                 :            :         default:
     694                 :            :         case TD_CMD_INVALID:
     695                 :            :                 ret = EINVAL;
     696                 :            :                 break;
     697                 :            :         }
     698                 :            : 
     699                 :          0 :         free(cargv);
     700                 :            : 
     701                 :          0 :         return (ret >= 0 ? ret : -ret);
     702                 :            : }

Generated by: LCOV version 1.13