/* * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in * case other systems have different values for MAXPATHLEN. * * The same must hold for V2 - we want file format compatibility, not anything * else.
*/ #define PATH_LEN_V3 4096 #define PATH_LEN_V2 PATH_LEN_V3
/* * Changes from V2 - * PATH_LEN_V3 as described above * Explicitly specify field bit lengths for systems with different * lengths for the usual C types. Not sure whether char or * time_t should be changed, this can be changed later without * breaking compatibility * Add alignment field so that different alignments can be used for the * bitmap and data * Add cow_format field to allow for the possibility of different ways * of specifying the COW blocks. For now, the only value is 0, * for the traditional COW bitmap. * Move the backing_file field to the end of the header. This allows * for the possibility of expanding it into the padding required * by the bitmap alignment. * The bitmap and data portions of the file will be aligned as specified * by the alignment field. This is to allow COW files to be * put on devices with restrictions on access alignments, such as * /dev/raw, with a 512 byte alignment restriction. This also * allows the data to be more aligned more strictly than on * sector boundaries. This is needed for ubd-mmap, which needs * the data to be page aligned. * Fixed (finally!) the rounding bug
*/
/* * Until Dec2005, __attribute__((packed)) was left out from the below * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to * align size to 8-byte alignment. This shifted all fields above (no padding * was present on 32-bit, no other padding was added). * * However, this _can be detected_: it means that cow_format (always 0 until * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise
* impossible to find 4 zeros. -bb */
staticint absolutize(char *to, int size, char *from)
{ char save_cwd[256], *slash; int remaining;
if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
cow_printf("absolutize : unable to get cwd - errno = %d\n",
errno); return -1;
}
slash = strrchr(from, '/'); if (slash != NULL) {
*slash = '\0'; if (chdir(from)) {
*slash = '/';
cow_printf("absolutize : Can't cd to '%s' - " "errno = %d\n", from, errno); return -1;
}
*slash = '/'; if (getcwd(to, size) == NULL) {
cow_printf("absolutize : unable to get cwd of '%s' - " "errno = %d\n", from, errno); return -1;
}
remaining = size - strlen(to); if (strlen(slash) + 1 > remaining) {
cow_printf("absolutize : unable to fit '%s' into %d " "chars\n", from, size); return -1;
}
strcat(to, slash);
} else { if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) {
cow_printf("absolutize : unable to fit '%s' into %d " "chars\n", from, size); return -1;
}
strcpy(to, save_cwd);
strcat(to, "/");
strcat(to, from);
} if (chdir(save_cwd)) {
cow_printf("absolutize : Can't cd to '%s' - " "errno = %d\n", save_cwd, errno); return -1;
} return 0;
}
int write_cow_header(char *cow_file, int fd, char *backing_file, int sectorsize, int alignment, unsignedlonglong *size)
{ struct cow_header_v3 *header; longlong modtime; int err;
err = -EINVAL; if (strlen(backing_file) > sizeof(header->backing_file) - 1) { /* Below, %zd is for a size_t value */
cow_printf("Backing file name \"%s\" is too long - names are " "limited to %zd characters\n", backing_file, sizeof(header->backing_file) - 1); goto out_free;
}
if (absolutize(header->backing_file, sizeof(header->backing_file),
backing_file)) goto out_free;
err = cow_write_file(fd, header, sizeof(*header)); if (err != sizeof(*header)) {
cow_printf("write_cow_header - write of header to " "new COW file '%s' failed, err = %d\n", cow_file,
-err); goto out_free;
}
err = 0;
out_free:
cow_free(header);
out: return err;
}
int file_reader(__u64 offset, char *buf, int len, void *arg)
{ int fd = *((int *) arg);
return pread(fd, buf, len, offset);
}
/* XXX Need to sanity-check the values read from the header */
int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
__u32 *version_out, char **backing_file_out, longlong *mtime_out, unsignedlonglong *size_out, int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out)
{ union cow_header *header; char *file; int err, n; unsignedlong version, magic;
header = cow_malloc(sizeof(*header)); if (header == NULL) {
cow_printf("read_cow_header - Failed to allocate header\n"); return -ENOMEM;
}
err = -EINVAL;
n = (*reader)(0, (char *) header, sizeof(*header), arg); if (n < offsetof(typeof(header->v1), backing_file)) {
cow_printf("read_cow_header - short header\n"); goto out;
}
magic = header->v1.magic; if (magic == COW_MAGIC)
version = header->v1.version; elseif (magic == be32toh(COW_MAGIC))
version = be32toh(header->v1.version); /* No error printed because the non-COW case comes through here */ elsegoto out;
if (n < sizeof(header->v3_b)) {
cow_printf("read_cow_header - failed to read V3 " "header\n"); goto out;
}
/* * this was used until Dec2005 - 64bits are needed to represent * 2106+. I.e. we can safely do this truncating cast. * * Additionally, we must use be32toh() instead of be64toh(), since * the program used to use the former (tested - I got mtime * mismatch "0 vs whatever"). *
* Ever heard about bug-to-bug-compatibility ? ;-) */
*mtime_out = (time32_t) be32toh(header->v3_b.mtime);
int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, int alignment, int *bitmap_offset_out, unsignedlong *bitmap_len_out, int *data_offset_out)
{ unsignedlonglong size, offset; char zero = 0; int err;
/* * does not really matter how much we write it is just to set EOF * this also sets the entire COW bitmap * to zero without having to allocate it
*/
err = cow_write_file(fd, &zero, sizeof(zero)); if (err != sizeof(zero)) {
cow_printf("Write of bitmap to new COW file '%s' failed, " "err = %d\n", cow_file, -err); if (err >= 0)
err = -EINVAL; goto out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.