LCOV - code coverage report
Current view: top level - include - libvhd.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 17 17.6 %
Date: 2025-03-10 18:15:27 Functions: 0 5 0.0 %
Branches: 0 76 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                 :            : #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                 :            : test_bit (const void *addr, uint32_t nr)
     175                 :            : {
     176                 :      12288 :         return (((const uint8_t *)addr)[nr >> 3] << (nr & 7)) & BIT_MASK;
     177                 :            : }
     178                 :            : 
     179                 :            : static inline void
     180                 :            : set_bit (void *addr, uint32_t nr)
     181                 :            : {
     182                 :       4097 :         ((uint8_t *)addr)[nr >> 3] |= (BIT_MASK >> (nr & 7));
     183                 :            : }
     184                 :            : 
     185                 :            : static inline void
     186                 :            : clear_bit (void *addr, uint32_t nr)
     187                 :            : {
     188                 :       4097 :         ((uint8_t *)addr)[nr >> 3] &= ~(BIT_MASK >> (nr & 7));
     189                 :            : }
     190                 :            : 
     191                 :            : static inline uint32_t
     192                 :            : 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                 :            : 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                 :            : vhd_sectors_to_bytes(uint64_t sectors)
     205                 :            : {
     206                 :          0 :         return sectors << VHD_SECTOR_SHIFT;
     207                 :            : }
     208                 :            : 
     209                 :            : static inline uint64_t
     210                 :            : 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                 :            : 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                 :            : 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                 :            : 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                 :            : int vhd_batmap_header_offset(vhd_context_t *ctx, off64_t *off);
     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 1.13