LCOV - code coverage report
Current view: top level - include - libvhd.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 20.7 % 29 6
Test Date: 2026-06-26 00:00:00 Functions: - 0 0
Branches: 0.0 % 160 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                 :             : #ifndef _VHD_LIB_H_
      32                 :             : #define _VHD_LIB_H_
      33                 :             : 
      34                 :             : /** \defgroup LibVHD LibVHD Module
      35                 :             :  * Core VHD handling
      36                 :             :  * @{
      37                 :             :  */
      38                 :             : 
      39                 :             : #include <string.h>
      40                 :             : #include <endian.h>
      41                 :             : #include <byteswap.h>
      42                 :             : #include <uuid/uuid.h>
      43                 :             : #include <stdbool.h>
      44                 :             : 
      45                 :             : #include "vhd.h"
      46                 :             : #include "list.h"
      47                 :             : 
      48                 :             : #if BYTE_ORDER == LITTLE_ENDIAN
      49                 :             :   #define BE16_IN(foo)             (*(foo)) = bswap_16(*(foo))
      50                 :             :   #define BE32_IN(foo)             (*(foo)) = bswap_32(*(foo))
      51                 :             :   #define BE64_IN(foo)             (*(foo)) = bswap_64(*(foo))
      52                 :             :   #define BE16_OUT(foo)            (*(foo)) = bswap_16(*(foo))
      53                 :             :   #define BE32_OUT(foo)            (*(foo)) = bswap_32(*(foo))
      54                 :             :   #define BE64_OUT(foo)            (*(foo)) = bswap_64(*(foo))
      55                 :             : #else
      56                 :             :   #define BE16_IN(foo)
      57                 :             :   #define BE32_IN(foo)
      58                 :             :   #define BE64_IN(foo)
      59                 :             :   #define BE32_OUT(foo)
      60                 :             :   #define BE32_OUT(foo)
      61                 :             :   #define BE64_OUT(foo)
      62                 :             : #endif
      63                 :             : 
      64                 :             : #define BIT_MASK                   0x80
      65                 :             : 
      66                 :             : #define MIN(a, b)                  (((a) < (b)) ? (a) : (b))
      67                 :             : #define MAX(a, b)                  (((a) > (b)) ? (a) : (b))
      68                 :             : 
      69                 :             : #define VHD_MAX_NAME_LEN           1024
      70                 :             : 
      71                 :             : #define VHD_BLOCK_SHIFT            21
      72                 :             : #define VHD_BLOCK_SIZE             (1ULL << VHD_BLOCK_SHIFT)
      73                 :             : 
      74                 :             : #define UTF_16                     "UTF-16"
      75                 :             : #define UTF_16LE                   "UTF-16LE"
      76                 :             : #define UTF_16BE                   "UTF-16BE"
      77                 :             : 
      78                 :             : #define VHD_OPEN_RDONLY            0x00001
      79                 :             : #define VHD_OPEN_RDWR              0x00002
      80                 :             : #define VHD_OPEN_FAST              0x00004
      81                 :             : #define VHD_OPEN_STRICT            0x00008
      82                 :             : #define VHD_OPEN_IGNORE_DISABLED   0x00010
      83                 :             : #define VHD_OPEN_CACHED            0x00020
      84                 :             : #define VHD_OPEN_IO_WRITE_SPARSE   0x00040
      85                 :             : #define VHD_OPEN_USE_BKP_FOOTER    0x00080
      86                 :             : 
      87                 :             : #define VHD_FLAG_CREAT_FILE_SIZE_FIXED   0x00001
      88                 :             : #define VHD_FLAG_CREAT_PARENT_RAW        0x00002
      89                 :             : 
      90                 :             : #define vhd_flag_set(word, flag)         ((word) |= (flag))
      91                 :             : #define vhd_flag_clear(word, flag)       ((word) &= ~(flag))
      92                 :             : #define vhd_flag_test(word, flag)        ((word) & (flag))
      93                 :             : 
      94                 :             : #define LIBBLOCKCRYPTO_NAME "libblockcrypto.so.0"
      95                 :             : 
      96                 :             : #define CRYPTO_DEFAULT_KEYDIR "/var/xen/blktap/keys"
      97                 :             : extern int CRYPTO_SUPPORTED_KEYSIZE[];
      98                 :             : 
      99                 :             : #define ENABLE_FAILURE_TESTING
     100                 :             : #define FAIL_REPARENT_BEGIN        0
     101                 :             : #define FAIL_REPARENT_LOCATOR      1
     102                 :             : #define FAIL_REPARENT_END          2
     103                 :             : #define FAIL_RESIZE_BEGIN          3
     104                 :             : #define FAIL_RESIZE_DATA_MOVED     4
     105                 :             : #define FAIL_RESIZE_METADATA_MOVED 5
     106                 :             : #define FAIL_RESIZE_END            6
     107                 :             : #define NUM_FAIL_TESTS             7
     108                 :             : 
     109                 :             : #ifdef ENABLE_FAILURE_TESTING
     110                 :             : #define TEST_FAIL_AT(point) \
     111                 :             :         if (TEST_FAIL[point]) { \
     112                 :             :                 printf("Failing at %s\n", ENV_VAR_FAIL[point]); exit(EINVAL); }
     113                 :             : #define TEST_FAIL_EXTERN_VARS              \
     114                 :             :         extern const char* ENV_VAR_FAIL[]; \
     115                 :             :         extern int TEST_FAIL[];
     116                 :             : #else
     117                 :             : #define TEST_FAIL_AT(point)
     118                 :             : #define TEST_FAIL_EXTERN_VARS
     119                 :             : #endif // ENABLE_FAILURE_TESTING
     120                 :             : 
     121                 :             : 
     122                 :             : static const char                  VHD_POISON_COOKIE[] = "v_poison";
     123                 :             : 
     124                 :             : typedef struct hd_ftr              vhd_footer_t;
     125                 :             : typedef struct dd_hdr              vhd_header_t;
     126                 :             : typedef struct vhd_bat             vhd_bat_t;
     127                 :             : typedef struct vhd_batmap          vhd_batmap_t;
     128                 :             : typedef struct dd_batmap_hdr       vhd_batmap_header_t;
     129                 :             : typedef struct prt_loc             vhd_parent_locator_t;
     130                 :             : typedef struct vhd_context         vhd_context_t;
     131                 :             : typedef uint32_t                   vhd_flag_creat_t;
     132                 :             : 
     133                 :             : struct vhd_bat {
     134                 :             :         uint32_t                   spb;
     135                 :             :         uint32_t                   entries;
     136                 :             :         uint32_t                  *bat;
     137                 :             : };
     138                 :             : 
     139                 :             : struct vhd_batmap {
     140                 :             :         vhd_batmap_header_t        header;
     141                 :             :         char                      *map;
     142                 :             : };
     143                 :             : 
     144                 :             : struct crypto_blkcipher;
     145                 :             : 
     146                 :             : struct vhd_context {
     147                 :             :         int                        fd;
     148                 :             :         char                      *file;
     149                 :             :         int                        oflags;
     150                 :             :         int                        is_block;
     151                 :             : 
     152                 :             :         off64_t                    offset;
     153                 :             :         uint32_t                   spb;
     154                 :             :         uint32_t                   bm_secs;
     155                 :             : 
     156                 :             :         vhd_header_t               header;
     157                 :             :         vhd_footer_t               footer;
     158                 :             :         vhd_bat_t                  bat;
     159                 :             :         vhd_batmap_t               batmap;
     160                 :             : 
     161                 :             :         struct crypto_blkcipher   *xts_tfm;
     162                 :             :         struct list_head           next;
     163                 :             : 
     164                 :             :         char                      *custom_parent;
     165                 :             : };
     166                 :             : 
     167                 :             : /* Helpers for manipulating bitmaps *
     168                 :             :  *
     169                 :             :  * The bitmap is stored on a per-byte basis with the MSB representing
     170                 :             :  * the first bit in the bitmap.
     171                 :             :  */
     172                 :             : 
     173                 :             : static inline bool
     174                 :       12288 : test_bit (const void *addr, uint32_t nr)
     175                 :             : {
     176   [ #  #  #  #  :        4096 :         return (((const uint8_t *)addr)[nr >> 3] << (nr & 7)) & BIT_MASK;
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     177                 :             : }
     178                 :             : 
     179                 :             : static inline void
     180                 :        4096 : set_bit (void *addr, uint32_t nr)
     181                 :             : {
     182                 :        4097 :         ((uint8_t *)addr)[nr >> 3] |= (BIT_MASK >> (nr & 7));
     183                 :           0 : }
     184                 :             : 
     185                 :             : static inline void
     186                 :        4096 : clear_bit (void *addr, uint32_t nr)
     187                 :             : {
     188                 :        4097 :         ((uint8_t *)addr)[nr >> 3] &= ~(BIT_MASK >> (nr & 7));
     189                 :           0 : }
     190                 :             : 
     191                 :             : static inline uint32_t
     192                 :           0 : secs_round_up(uint64_t bytes)
     193                 :             : {
     194         [ #  # ]:           0 :         return ((bytes + (VHD_SECTOR_SIZE - 1)) >> VHD_SECTOR_SHIFT);
     195                 :             : }
     196                 :             : 
     197                 :             : static inline uint32_t
     198         [ #  # ]:           0 : secs_round_up_no_zero(uint64_t bytes)
     199                 :             : {
     200   [ #  #  #  #  :           0 :         return (secs_round_up(bytes) ? : 1);
          #  #  #  #  #  
                      # ]
     201                 :             : }
     202                 :             : 
     203                 :             : static inline uint64_t
     204                 :           0 : vhd_sectors_to_bytes(uint64_t sectors)
     205                 :             : {
     206   [ #  #  #  #  :           0 :         return sectors << VHD_SECTOR_SHIFT;
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     207                 :             : }
     208                 :             : 
     209                 :             : static inline uint64_t
     210                 :           0 : vhd_bytes_padded(uint64_t bytes)
     211                 :             : {
     212   [ #  #  #  #  :           0 :         return vhd_sectors_to_bytes(secs_round_up_no_zero(bytes));
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     213                 :             : }
     214                 :             : 
     215                 :             : static inline int
     216                 :           0 : vhd_type_dynamic(vhd_context_t *ctx)
     217                 :             : {
     218   [ #  #  #  #  :           0 :         return (ctx->footer.type == HD_TYPE_DYNAMIC ||
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     219                 :             :                 ctx->footer.type == HD_TYPE_DIFF);
     220                 :             : }
     221                 :             : 
     222                 :             : static inline int
     223                 :           0 : vhd_creator_tapdisk(vhd_context_t *ctx)
     224                 :             : {
     225   [ #  #  #  #  :           0 :         return !strncmp(ctx->footer.crtr_app, "tap", 3);
             #  #  #  # ]
     226                 :             : }
     227                 :             : 
     228                 :             : static inline int
     229                 :           0 : vhd_disabled(vhd_context_t *ctx)
     230                 :             : {
     231         [ #  # ]:           0 :         return (!memcmp(ctx->footer.cookie,
     232                 :             :                         VHD_POISON_COOKIE, sizeof(ctx->footer.cookie)));
     233                 :             : }
     234                 :             : 
     235                 :             : static inline size_t
     236                 :           0 : vhd_parent_locator_size(vhd_parent_locator_t *loc)
     237                 :             : {
     238                 :             :         /*
     239                 :             :          * MICROSOFT_COMPAT
     240                 :             :          * data_space *should* be in sectors,
     241                 :             :          * but sometimes we find it in bytes
     242                 :             :          */
     243   [ #  #  #  #  :           0 :         if (loc->data_space < 512)
             #  #  #  # ]
     244                 :           0 :                 return vhd_sectors_to_bytes(loc->data_space);
     245   [ #  #  #  #  :           0 :         else if (loc->data_space % 512 == 0)
             #  #  #  # ]
     246                 :           0 :                 return loc->data_space;
     247                 :             :         else
     248                 :             :                 return 0;
     249                 :             : }
     250                 :             : 
     251                 :             : static inline int
     252                 :           0 : vhd_parent_raw(vhd_context_t *ctx)
     253                 :             : {
     254                 :           0 :         return uuid_is_null(ctx->header.prt_uuid);
     255                 :             : }
     256                 :             : 
     257                 :             : int open_optional_odirect(const char *pathname, int flags, ...);
     258                 :             : 
     259                 :             : void libvhd_set_log_level(int);
     260                 :             : 
     261                 :             : int vhd_test_file_fixed(const char *, int *);
     262                 :             : 
     263                 :             : uint32_t vhd_time(time_t time);
     264                 :             : size_t vhd_time_to_string(uint32_t timestamp, char *target);
     265                 :             : uint32_t vhd_chs(uint64_t size);
     266                 :             : 
     267                 :             : uint32_t vhd_checksum_footer(vhd_footer_t *);
     268                 :             : uint32_t vhd_checksum_header(vhd_header_t *);
     269                 :             : uint32_t vhd_checksum_batmap(vhd_context_t *, vhd_batmap_t *);
     270                 :             : 
     271                 :             : void vhd_footer_in(vhd_footer_t *);
     272                 :             : void vhd_footer_out(vhd_footer_t *);
     273                 :             : void vhd_header_in(vhd_header_t *);
     274                 :             : void vhd_header_out(vhd_header_t *);
     275                 :             : void vhd_bat_in(vhd_bat_t *);
     276                 :             : void vhd_bat_out(vhd_bat_t *);
     277                 :             : void vhd_batmap_header_in(vhd_batmap_t *);
     278                 :             : void vhd_batmap_header_out(vhd_batmap_t *);
     279                 :             : 
     280                 :             : int vhd_validate_footer(vhd_footer_t *footer);
     281                 :             : int vhd_validate_header(vhd_header_t *header);
     282                 :             : int vhd_validate_batmap_header(vhd_batmap_t *batmap);
     283                 :             : int vhd_validate_batmap(vhd_context_t *, vhd_batmap_t *batmap);
     284                 :             : int vhd_validate_platform_code(uint32_t code);
     285                 :             : 
     286                 :             : int vhd_open(vhd_context_t *, const char *file, int flags);
     287                 :             : void vhd_close(vhd_context_t *);
     288                 :             : /* vhd_create: mbytes is the virtual size for BAT/batmap preallocation - see 
     289                 :             :  * vhd-util-resize.c
     290                 :             :  */
     291                 :             : int vhd_create(const char *name, uint64_t bytes, int type, uint64_t mbytes,
     292                 :             :                 vhd_flag_creat_t);
     293                 :             : /* vhd_snapshot: the bytes parameter is optional and can be 0 if the snapshot 
     294                 :             :  * is to have the same size as the (first non-empty) parent */
     295                 :             : int vhd_snapshot(const char *snapshot, uint64_t bytes, const char *parent,
     296                 :             :                 uint64_t mbytes, vhd_flag_creat_t);
     297                 :             : 
     298                 :             : int vhd_hidden(vhd_context_t *, int *);
     299                 :             : int vhd_chain_depth(vhd_context_t *, int *);
     300                 :             : int vhd_marker(vhd_context_t *, char *);   
     301                 :             : int vhd_set_marker(vhd_context_t *, char); 
     302                 :             : int vhd_get_keyhash(vhd_context_t *, struct vhd_keyhash *);
     303                 :             : int vhd_set_keyhash(vhd_context_t *, const struct vhd_keyhash *);
     304                 :             : 
     305                 :             : off64_t vhd_position(vhd_context_t *);
     306                 :             : int vhd_seek(vhd_context_t *, off64_t, int);
     307                 :             : int vhd_read(vhd_context_t *, void *, size_t);
     308                 :             : int vhd_write(vhd_context_t *, void *, size_t);
     309                 :             : 
     310                 :             : int vhd_offset(vhd_context_t *, uint32_t, uint32_t *);
     311                 :             : 
     312                 :             : int vhd_end_of_headers(vhd_context_t *ctx, off64_t *off);
     313                 :             : int vhd_end_of_data(vhd_context_t *ctx, off64_t *off);
     314                 :             : off64_t vhd_batmap_header_offset(vhd_context_t *ctx);
     315                 :             : 
     316                 :             : int vhd_get_header(vhd_context_t *);
     317                 :             : int vhd_get_footer(vhd_context_t *);
     318                 :             : int vhd_get_bat(vhd_context_t *);
     319                 :             : int vhd_get_batmap(vhd_context_t *);
     320                 :             : 
     321                 :             : void vhd_put_header(vhd_context_t *);
     322                 :             : void vhd_put_footer(vhd_context_t *);
     323                 :             : void vhd_put_bat(vhd_context_t *);
     324                 :             : void vhd_put_batmap(vhd_context_t *);
     325                 :             : 
     326                 :             : int vhd_has_batmap(vhd_context_t *);
     327                 :             : int vhd_batmap_test(vhd_context_t *, vhd_batmap_t *, uint32_t);
     328                 :             : void vhd_batmap_set(vhd_context_t *, vhd_batmap_t *, uint32_t);
     329                 :             : void vhd_batmap_clear(vhd_context_t *, vhd_batmap_t *, uint32_t);
     330                 :             : 
     331                 :             : int vhd_file_size_fixed(vhd_context_t *);
     332                 :             : int vhd_get_phys_size(vhd_context_t *, off64_t *);
     333                 :             : int vhd_set_phys_size(vhd_context_t *, off64_t);
     334                 :             : int vhd_set_virt_size(vhd_context_t *, uint64_t);
     335                 :             : 
     336                 :             : int vhd_bitmap_test(vhd_context_t *, char *, uint32_t);
     337                 :             : void vhd_bitmap_set(vhd_context_t *, char *, uint32_t);
     338                 :             : void vhd_bitmap_clear(vhd_context_t *, char *, uint32_t);
     339                 :             : 
     340                 :             : int vhd_initialize_header_parent_name(vhd_context_t *, const char *);
     341                 :             : int vhd_write_parent_locators(vhd_context_t *, const char *);
     342                 :             : int vhd_parent_locator_count(vhd_context_t *);
     343                 :             : int vhd_parent_locator_get(vhd_context_t *, char **);
     344                 :             : int vhd_parent_locator_unresolved_get(vhd_context_t *, char **);
     345                 :             : int vhd_custom_parent_set(vhd_context_t *vhd, const char *parent);
     346                 :             : 
     347                 :             : int vhd_parent_locator_read(vhd_context_t *, vhd_parent_locator_t *, char **);
     348                 :             : int vhd_find_parent(vhd_context_t *, const char *, char **);
     349                 :             : int vhd_parent_locator_write_at(vhd_context_t *, const char *,
     350                 :             :                                 off64_t, uint32_t, size_t,
     351                 :             :                                 vhd_parent_locator_t *);
     352                 :             : 
     353                 :             : int vhd_header_decode_parent(vhd_context_t *, vhd_header_t *, char **);
     354                 :             : int vhd_change_parent(vhd_context_t *, char *parent_path, int raw);
     355                 :             : int vhd_macx_encode_location(char *name, char **out, int *outlen);
     356                 :             : int vhd_w2u_encode_location(char *name, char **out, int *outlen);
     357                 :             : 
     358                 :             : int vhd_read_footer(vhd_context_t *, vhd_footer_t *, bool use_bkp_footer);
     359                 :             : int vhd_read_footer_at(vhd_context_t *, vhd_footer_t *, off64_t);
     360                 :             : int vhd_read_footer_strict(vhd_context_t *, vhd_footer_t *);
     361                 :             : int vhd_read_header(vhd_context_t *, vhd_header_t *);
     362                 :             : int vhd_read_header_at(vhd_context_t *, vhd_header_t *, off64_t);
     363                 :             : int vhd_read_bat(vhd_context_t *, vhd_bat_t *);
     364                 :             : int vhd_read_batmap(vhd_context_t *, vhd_batmap_t *);
     365                 :             : int vhd_read_bitmap(vhd_context_t *, uint32_t block, char **bufp);
     366                 :             : int vhd_read_at(vhd_context_t *ctx, uint64_t block, uint32_t from, size_t size, char *buf);
     367                 :             : int vhd_read_block(vhd_context_t *, uint32_t block, char **bufp);
     368                 :             : 
     369                 :             : int vhd_write_footer(vhd_context_t *, vhd_footer_t *);
     370                 :             : int vhd_write_footer_at(vhd_context_t *, vhd_footer_t *, off64_t);
     371                 :             : int vhd_write_header(vhd_context_t *, vhd_header_t *);
     372                 :             : int vhd_write_header_at(vhd_context_t *, vhd_header_t *, off64_t);
     373                 :             : int vhd_write_bat(vhd_context_t *, vhd_bat_t *);
     374                 :             : int vhd_write_batmap(vhd_context_t *, vhd_batmap_t *);
     375                 :             : int vhd_write_bitmap(vhd_context_t *, uint32_t block, char *bitmap);
     376                 :             : int vhd_write_block(vhd_context_t *, uint32_t block, char *data);
     377                 :             : 
     378                 :             : int vhd_io_read(vhd_context_t *, char *, uint64_t, uint32_t);
     379                 :             : int vhd_io_write(vhd_context_t *, char *, uint64_t, uint32_t);
     380                 :             : int vhd_io_read_bytes(vhd_context_t *, void *, size_t, uint64_t);
     381                 :             : int vhd_io_write_bytes(vhd_context_t *, void *, size_t, uint64_t);
     382                 :             : 
     383                 :             : /** @} */ // End of LibVHD Doxygen group
     384                 :             : 
     385                 :             : #endif
        

Generated by: LCOV version 2.0-1