-#if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x) bswap_64(x)
-# define htonll(x) bswap_64(x)
-#else
-#error "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
- int magic;
- int version;
- char backing_file[PATH_LEN_V1];
- time_t mtime;
- __u64 size;
- int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
- unsigned long magic;
- unsigned long version;
- char backing_file[PATH_LEN_V2];
- time_t mtime;
- __u64 size;
- int sectorsize;
-};
-
-union cow_header {
- struct cow_header_v1 v1;
- struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset,
- unsigned long *bitmap_len_out, int *data_offset_out)
-{
- *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
- *data_offset_out = bitmap_offset + *bitmap_len_out;
- *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
- *data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out,
- time_t *mtime_out, __u64 *size_out,
- int *sectorsize_out, int *bitmap_offset_out)
-{
- union cow_header *header;
- char *file;
- int err, n;
- unsigned long version, magic;
-
- header = um_kmalloc(sizeof(*header));
- if(header == NULL){
- printk("read_cow_header - Failed to allocate header\n");
- return(-ENOMEM);
- }
- err = -EINVAL;
- n = read(fd, header, sizeof(*header));
- if(n < offsetof(typeof(header->v1), backing_file)){
- printk("read_cow_header - short header\n");
- goto out;
- }
-
- magic = header->v1.magic;
- if(magic == COW_MAGIC) {
- version = header->v1.version;
- }
- else if(magic == ntohl(COW_MAGIC)){
- version = ntohl(header->v1.version);
- }
- else goto out;
-
- *magic_out = COW_MAGIC;
-
- if(version == 1){
- if(n < sizeof(header->v1)){
- printk("read_cow_header - failed to read V1 header\n");
- goto out;
- }
- *mtime_out = header->v1.mtime;
- *size_out = header->v1.size;
- *sectorsize_out = header->v1.sectorsize;
- *bitmap_offset_out = sizeof(header->v1);
- file = header->v1.backing_file;
- }
- else if(version == 2){
- if(n < sizeof(header->v2)){
- printk("read_cow_header - failed to read V2 header\n");
- goto out;
- }
- *mtime_out = ntohl(header->v2.mtime);
- *size_out = ntohll(header->v2.size);
- *sectorsize_out = ntohl(header->v2.sectorsize);
- *bitmap_offset_out = sizeof(header->v2);
- file = header->v2.backing_file;
- }
- else {
- printk("read_cow_header - invalid COW version\n");
- goto out;
- }
- err = -ENOMEM;
- *backing_file_out = uml_strdup(file);
- if(*backing_file_out == NULL){
- printk("read_cow_header - failed to allocate backing file\n");
- goto out;
- }
- err = 0;
- out:
- kfree(header);
- return(err);
-}