1 /* 2 * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 3 * Licensed under the GPL 4 */ 5 6 /* 7 * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines 8 * that. 9 */ 10 #include <unistd.h> 11 #include <byteswap.h> 12 #include <errno.h> 13 #include <string.h> 14 #include <arpa/inet.h> 15 #include <asm/types.h> 16 #include "cow.h" 17 #include "cow_sys.h" 18 19 #define PATH_LEN_V1 256 20 21 typedef __u32 time32_t; 22 23 struct cow_header_v1 { 24 __s32 magic; 25 __s32 version; 26 char backing_file[PATH_LEN_V1]; 27 time32_t mtime; 28 __u64 size; 29 __s32 sectorsize; 30 } __attribute__((packed)); 31 32 /* 33 * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in 34 * case other systems have different values for MAXPATHLEN. 35 * 36 * The same must hold for V2 - we want file format compatibility, not anything 37 * else. 38 */ 39 #define PATH_LEN_V3 4096 40 #define PATH_LEN_V2 PATH_LEN_V3 41 42 struct cow_header_v2 { 43 __u32 magic; 44 __u32 version; 45 char backing_file[PATH_LEN_V2]; 46 time32_t mtime; 47 __u64 size; 48 __s32 sectorsize; 49 } __attribute__((packed)); 50 51 /* 52 * Changes from V2 - 53 * PATH_LEN_V3 as described above 54 * Explicitly specify field bit lengths for systems with different 55 * lengths for the usual C types. Not sure whether char or 56 * time_t should be changed, this can be changed later without 57 * breaking compatibility 58 * Add alignment field so that different alignments can be used for the 59 * bitmap and data 60 * Add cow_format field to allow for the possibility of different ways 61 * of specifying the COW blocks. For now, the only value is 0, 62 * for the traditional COW bitmap. 63 * Move the backing_file field to the end of the header. This allows 64 * for the possibility of expanding it into the padding required 65 * by the bitmap alignment. 66 * The bitmap and data portions of the file will be aligned as specified 67 * by the alignment field. This is to allow COW files to be 68 * put on devices with restrictions on access alignments, such as 69 * /dev/raw, with a 512 byte alignment restriction. This also 70 * allows the data to be more aligned more strictly than on 71 * sector boundaries. This is needed for ubd-mmap, which needs 72 * the data to be page aligned. 73 * Fixed (finally!) the rounding bug 74 */ 75 76 /* 77 * Until Dec2005, __attribute__((packed)) was left out from the below 78 * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to 79 * align size to 8-byte alignment. This shifted all fields above (no padding 80 * was present on 32-bit, no other padding was added). 81 * 82 * However, this _can be detected_: it means that cow_format (always 0 until 83 * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise 84 * impossible to find 4 zeros. -bb */ 85 86 struct cow_header_v3 { 87 __u32 magic; 88 __u32 version; 89 __u32 mtime; 90 __u64 size; 91 __u32 sectorsize; 92 __u32 alignment; 93 __u32 cow_format; 94 char backing_file[PATH_LEN_V3]; 95 } __attribute__((packed)); 96 97 /* This is the broken layout used by some 64-bit binaries. */ 98 struct cow_header_v3_broken { 99 __u32 magic; 100 __u32 version; 101 __s64 mtime; 102 __u64 size; 103 __u32 sectorsize; 104 __u32 alignment; 105 __u32 cow_format; 106 char backing_file[PATH_LEN_V3]; 107 }; 108 109 /* COW format definitions - for now, we have only the usual COW bitmap */ 110 #define COW_BITMAP 0 111 112 union cow_header { 113 struct cow_header_v1 v1; 114 struct cow_header_v2 v2; 115 struct cow_header_v3 v3; 116 struct cow_header_v3_broken v3_b; 117 }; 118 119 #define COW_MAGIC 0x4f4f4f4d /* MOOO */ 120 #define COW_VERSION 3 121 122 #define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) 123 #define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) 124 125 void cow_sizes(int version, __u64 size, int sectorsize, int align, 126 int bitmap_offset, unsigned long *bitmap_len_out, 127 int *data_offset_out) 128 { 129 if (version < 3) { 130 *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); 131 132 *data_offset_out = bitmap_offset + *bitmap_len_out; 133 *data_offset_out = (*data_offset_out + sectorsize - 1) / 134 sectorsize; 135 *data_offset_out *= sectorsize; 136 } 137 else { 138 *bitmap_len_out = DIV_ROUND(size, sectorsize); 139 *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8); 140 141 *data_offset_out = bitmap_offset + *bitmap_len_out; 142 *data_offset_out = ROUND_UP(*data_offset_out, align); 143 } 144 } 145 146 static int absolutize(char *to, int size, char *from) 147 { 148 char save_cwd[256], *slash; 149 int remaining; 150 151 if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) { 152 cow_printf("absolutize : unable to get cwd - errno = %d\n", 153 errno); 154 return -1; 155 } 156 slash = strrchr(from, '/'); 157 if (slash != NULL) { 158 *slash = '\0'; 159 if (chdir(from)) { 160 *slash = '/'; 161 cow_printf("absolutize : Can't cd to '%s' - " 162 "errno = %d\n", from, errno); 163 return -1; 164 } 165 *slash = '/'; 166 if (getcwd(to, size) == NULL) { 167 cow_printf("absolutize : unable to get cwd of '%s' - " 168 "errno = %d\n", from, errno); 169 return -1; 170 } 171 remaining = size - strlen(to); 172 if (strlen(slash) + 1 > remaining) { 173 cow_printf("absolutize : unable to fit '%s' into %d " 174 "chars\n", from, size); 175 return -1; 176 } 177 strcat(to, slash); 178 } 179 else { 180 if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) { 181 cow_printf("absolutize : unable to fit '%s' into %d " 182 "chars\n", from, size); 183 return -1; 184 } 185 strcpy(to, save_cwd); 186 strcat(to, "/"); 187 strcat(to, from); 188 } 189 chdir(save_cwd); 190 return 0; 191 } 192 193 int write_cow_header(char *cow_file, int fd, char *backing_file, 194 int sectorsize, int alignment, unsigned long long *size) 195 { 196 struct cow_header_v3 *header; 197 unsigned long modtime; 198 int err; 199 200 err = cow_seek_file(fd, 0); 201 if (err < 0) { 202 cow_printf("write_cow_header - lseek failed, err = %d\n", -err); 203 goto out; 204 } 205 206 err = -ENOMEM; 207 header = cow_malloc(sizeof(*header)); 208 if (header == NULL) { 209 cow_printf("write_cow_header - failed to allocate COW V3 " 210 "header\n"); 211 goto out; 212 } 213 header->magic = htonl(COW_MAGIC); 214 header->version = htonl(COW_VERSION); 215 216 err = -EINVAL; 217 if (strlen(backing_file) > sizeof(header->backing_file) - 1) { 218 /* Below, %zd is for a size_t value */ 219 cow_printf("Backing file name \"%s\" is too long - names are " 220 "limited to %zd characters\n", backing_file, 221 sizeof(header->backing_file) - 1); 222 goto out_free; 223 } 224 225 if (absolutize(header->backing_file, sizeof(header->backing_file), 226 backing_file)) 227 goto out_free; 228 229 err = os_file_modtime(header->backing_file, &modtime); 230 if (err < 0) { 231 cow_printf("write_cow_header - backing file '%s' mtime " 232 "request failed, err = %d\n", header->backing_file, 233 -err); 234 goto out_free; 235 } 236 237 err = cow_file_size(header->backing_file, size); 238 if (err < 0) { 239 cow_printf("write_cow_header - couldn't get size of " 240 "backing file '%s', err = %d\n", 241 header->backing_file, -err); 242 goto out_free; 243 } 244 245 header->mtime = htonl(modtime); 246 header->size = htonll(*size); 247 header->sectorsize = htonl(sectorsize); 248 header->alignment = htonl(alignment); 249 header->cow_format = COW_BITMAP; 250 251 err = cow_write_file(fd, header, sizeof(*header)); 252 if (err != sizeof(*header)) { 253 cow_printf("write_cow_header - write of header to " 254 "new COW file '%s' failed, err = %d\n", cow_file, 255 -err); 256 goto out_free; 257 } 258 err = 0; 259 out_free: 260 cow_free(header); 261 out: 262 return err; 263 } 264 265 int file_reader(__u64 offset, char *buf, int len, void *arg) 266 { 267 int fd = *((int *) arg); 268 269 return pread(fd, buf, len, offset); 270 } 271 272 /* XXX Need to sanity-check the values read from the header */ 273 274 int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, 275 __u32 *version_out, char **backing_file_out, 276 time_t *mtime_out, unsigned long long *size_out, 277 int *sectorsize_out, __u32 *align_out, 278 int *bitmap_offset_out) 279 { 280 union cow_header *header; 281 char *file; 282 int err, n; 283 unsigned long version, magic; 284 285 header = cow_malloc(sizeof(*header)); 286 if (header == NULL) { 287 cow_printf("read_cow_header - Failed to allocate header\n"); 288 return -ENOMEM; 289 } 290 err = -EINVAL; 291 n = (*reader)(0, (char *) header, sizeof(*header), arg); 292 if (n < offsetof(typeof(header->v1), backing_file)) { 293 cow_printf("read_cow_header - short header\n"); 294 goto out; 295 } 296 297 magic = header->v1.magic; 298 if (magic == COW_MAGIC) 299 version = header->v1.version; 300 else if (magic == ntohl(COW_MAGIC)) 301 version = ntohl(header->v1.version); 302 /* No error printed because the non-COW case comes through here */ 303 else goto out; 304 305 *version_out = version; 306 307 if (version == 1) { 308 if (n < sizeof(header->v1)) { 309 cow_printf("read_cow_header - failed to read V1 " 310 "header\n"); 311 goto out; 312 } 313 *mtime_out = header->v1.mtime; 314 *size_out = header->v1.size; 315 *sectorsize_out = header->v1.sectorsize; 316 *bitmap_offset_out = sizeof(header->v1); 317 *align_out = *sectorsize_out; 318 file = header->v1.backing_file; 319 } 320 else if (version == 2) { 321 if (n < sizeof(header->v2)) { 322 cow_printf("read_cow_header - failed to read V2 " 323 "header\n"); 324 goto out; 325 } 326 *mtime_out = ntohl(header->v2.mtime); 327 *size_out = ntohll(header->v2.size); 328 *sectorsize_out = ntohl(header->v2.sectorsize); 329 *bitmap_offset_out = sizeof(header->v2); 330 *align_out = *sectorsize_out; 331 file = header->v2.backing_file; 332 } 333 /* This is very subtle - see above at union cow_header definition */ 334 else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) { 335 if (n < sizeof(header->v3)) { 336 cow_printf("read_cow_header - failed to read V3 " 337 "header\n"); 338 goto out; 339 } 340 *mtime_out = ntohl(header->v3.mtime); 341 *size_out = ntohll(header->v3.size); 342 *sectorsize_out = ntohl(header->v3.sectorsize); 343 *align_out = ntohl(header->v3.alignment); 344 if (*align_out == 0) { 345 cow_printf("read_cow_header - invalid COW header, " 346 "align == 0\n"); 347 } 348 *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); 349 file = header->v3.backing_file; 350 } 351 else if (version == 3) { 352 cow_printf("read_cow_header - broken V3 file with" 353 " 64-bit layout - recovering content.\n"); 354 355 if (n < sizeof(header->v3_b)) { 356 cow_printf("read_cow_header - failed to read V3 " 357 "header\n"); 358 goto out; 359 } 360 361 /* 362 * this was used until Dec2005 - 64bits are needed to represent 363 * 2038+. I.e. we can safely do this truncating cast. 364 * 365 * Additionally, we must use ntohl() instead of ntohll(), since 366 * the program used to use the former (tested - I got mtime 367 * mismatch "0 vs whatever"). 368 * 369 * Ever heard about bug-to-bug-compatibility ? ;-) */ 370 *mtime_out = (time32_t) ntohl(header->v3_b.mtime); 371 372 *size_out = ntohll(header->v3_b.size); 373 *sectorsize_out = ntohl(header->v3_b.sectorsize); 374 *align_out = ntohl(header->v3_b.alignment); 375 if (*align_out == 0) { 376 cow_printf("read_cow_header - invalid COW header, " 377 "align == 0\n"); 378 } 379 *bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out); 380 file = header->v3_b.backing_file; 381 } 382 else { 383 cow_printf("read_cow_header - invalid COW version\n"); 384 goto out; 385 } 386 err = -ENOMEM; 387 *backing_file_out = cow_strdup(file); 388 if (*backing_file_out == NULL) { 389 cow_printf("read_cow_header - failed to allocate backing " 390 "file\n"); 391 goto out; 392 } 393 err = 0; 394 out: 395 cow_free(header); 396 return err; 397 } 398 399 int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, 400 int alignment, int *bitmap_offset_out, 401 unsigned long *bitmap_len_out, int *data_offset_out) 402 { 403 unsigned long long size, offset; 404 char zero = 0; 405 int err; 406 407 err = write_cow_header(cow_file, fd, backing_file, sectorsize, 408 alignment, &size); 409 if (err) 410 goto out; 411 412 *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); 413 cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, 414 bitmap_len_out, data_offset_out); 415 416 offset = *data_offset_out + size - sizeof(zero); 417 err = cow_seek_file(fd, offset); 418 if (err < 0) { 419 cow_printf("cow bitmap lseek failed : err = %d\n", -err); 420 goto out; 421 } 422 423 /* 424 * does not really matter how much we write it is just to set EOF 425 * this also sets the entire COW bitmap 426 * to zero without having to allocate it 427 */ 428 err = cow_write_file(fd, &zero, sizeof(zero)); 429 if (err != sizeof(zero)) { 430 cow_printf("Write of bitmap to new COW file '%s' failed, " 431 "err = %d\n", cow_file, -err); 432 if (err >= 0) 433 err = -EINVAL; 434 goto out; 435 } 436 437 return 0; 438 out: 439 return err; 440 } 441