~ubuntu-branches/ubuntu/raring/uml-utilities/raring

« back to all changes in this revision

Viewing changes to moo/uml_moo.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-04-14 17:59:45 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040414175945-olq69xkt2da1oxca
Tags: 20040406-1
* New upstream release
* Patch from Carlos Perelló Marín to fix uml_proxy_arp with multiple
  addresses (Closes: #243834)

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 * Licensed under the GPL
4
4
 */ 
5
5
 
 
6
#define _XOPEN_SOURCE 500
 
7
 
6
8
#include <stdio.h>
7
9
#include <stdlib.h>
8
10
#include <unistd.h>
9
11
#include <errno.h>
10
12
#include <time.h>
11
13
#include <fcntl.h>
 
14
#include <string.h>
12
15
#include <byteswap.h>
13
16
#include <sys/stat.h>
14
17
#include <sys/types.h>
15
18
#include <sys/param.h>
16
 
#include <netinet/in.h>
17
 
 
18
 
#if __BYTE_ORDER == __BIG_ENDIAN
19
 
# define ntohll(x) (x)
20
 
# define htonll(x) (x)
21
 
#elif __BYTE_ORDER == __LITTLE_ENDIAN
22
 
# define ntohll(x)  bswap_64(x)
23
 
# define htonll(x)  bswap_64(x)
24
 
#else
25
 
#error "__BYTE_ORDER not defined"
26
 
#endif
27
 
 
28
 
typedef long long u64;
29
 
 
30
 
/* XXX All these fields should be word-length independent */
31
 
 
32
 
struct cow_header_common {
33
 
       unsigned long magic;
34
 
       unsigned long version;
35
 
};
36
 
 
37
 
/* taken from ubd_user.c */
38
 
 
39
 
#define PATH_LEN_V1 256
40
 
 
41
 
struct cow_header_v1 {
42
 
        struct cow_header_common common;
43
 
        char backing_file[PATH_LEN_V1];
44
 
        time_t mtime;
45
 
        u64 size;
46
 
        int sectorsize;
47
 
};
48
 
 
49
 
#define PATH_LEN_V2 MAXPATHLEN
50
 
 
51
 
struct cow_header_v2 {
52
 
        struct cow_header_common common;
53
 
        char backing_file[PATH_LEN_V2];
54
 
        time_t mtime;
55
 
        u64 size;
56
 
        int sectorsize;
57
 
};
58
 
 
59
 
union cow_header {
60
 
       struct cow_header_v1 v1;
61
 
       struct cow_header_v2 v2;
62
 
};
63
 
 
64
 
#define COW_MAGIC 0x4f4f4f4d  /* mooo */
65
 
#define COW_VERSION 1
 
19
#include "cow.h"
66
20
 
67
21
static inline int ubd_test_bit(int bit, unsigned long *data)
68
22
{
84
38
        data[n] |= (1 << off);
85
39
}
86
40
 
87
 
static void sizes(u64 size, int sectorsize, int bitmap_offset, 
88
 
                  int *bitmap_len_out, int *data_offset_out)
89
 
{
90
 
        *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
91
 
 
92
 
        *data_offset_out = bitmap_offset + *bitmap_len_out;
93
 
        *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
94
 
        *data_offset_out *= sectorsize;
95
 
}
96
 
 
97
 
int create_backing_file(int argc, char *argv[])
98
 
{
99
 
        char *in = argv[1];
100
 
        char *out = argv[2];
 
41
int create_backing_file(char *in, char *out, char *actual_backing)
 
42
{
101
43
        int cow_fd, back_fd, in_fd, out_fd;
102
 
        struct stat64 buf;
 
44
        struct stat buf;
103
45
        unsigned long *bitmap;
104
 
        int bitmap_len;
105
 
        int blocks;
106
 
        char * block;
107
 
        int i;
108
 
        u64 offset;
109
 
        union cow_header header;
110
 
        struct cow_header_common common;
 
46
        unsigned long bitmap_len;
 
47
        int sectors;
 
48
        void *sector, *zeros;
 
49
        __u64 size, offset, i; /* i is u64 to prevent 32 bit overflow */
 
50
        __u32 version, alignment;
111
51
        int data_offset;
112
 
        unsigned long magic, version;
113
52
        char *backing_file;
114
53
        time_t mtime;
115
 
        u64 size;
116
 
        int sectorsize, bitmap_offset;
 
54
        int sectorsize, bitmap_offset, perms, n;
117
55
 
118
56
        if((cow_fd = open(in,  O_RDONLY)) < 0){
119
57
                perror("COW file open");
120
58
                exit(1);
121
59
        }
122
 
        if((out_fd = creat(out, 0644)) < 0){
123
 
                perror("Output file open");
124
 
                exit(1);
125
 
        }
126
 
 
127
 
        if(read(cow_fd, &common, sizeof(common)) != sizeof(common)){
128
 
                perror("COW common header read");
129
 
                exit(1);
130
 
        }
131
 
        if(lseek64(cow_fd, 0, SEEK_SET) != 0){
132
 
                perror("seeking back to COW file start");
133
 
                exit(1);
134
 
        }
135
 
 
136
 
        magic = common.magic;
137
 
        if(magic == COW_MAGIC) version = common.version;
138
 
        else if(magic == ntohl(COW_MAGIC)) version = ntohl(common.version);
139
 
        else {
140
 
                fprintf(stderr,"magic number (0x%x) doesn't match COW_MAGIC "
141
 
                        "(0x%x)\n", (unsigned int) magic, COW_MAGIC);
142
 
                exit(1);
143
 
        }
144
 
 
145
 
        if(version == 1){
146
 
                if(read(cow_fd, &header.v1, sizeof(header.v1)) != 
147
 
                   sizeof(header.v1)){
148
 
                        perror("Reading full V1 COW header");
149
 
                        exit(1);
150
 
                }
151
 
                backing_file = header.v1.backing_file;
152
 
                size = header.v1.size;
153
 
                mtime = header.v1.mtime;
154
 
                sectorsize = header.v1.sectorsize;
155
 
                bitmap_offset = sizeof(header.v1);
156
 
        }
157
 
        else if(version == 2){
158
 
                if(read(cow_fd, &header.v2, sizeof(header.v2)) != 
159
 
                   sizeof(header.v2)){
160
 
                        perror("Reading full V2 COW header");
161
 
                        exit(1);
162
 
                }
163
 
                backing_file = header.v2.backing_file;
164
 
                size = ntohll(header.v2.size);
165
 
                mtime = ntohl(header.v2.mtime);
166
 
                sectorsize = ntohl(header.v2.sectorsize);
167
 
                bitmap_offset = sizeof(header.v2);
168
 
        } 
169
 
        else {
170
 
                fprintf(stderr,"Unknown version %ld\n", version);
171
 
                exit(1);
172
 
        }
173
 
 
174
 
        if(stat64(backing_file, &buf) < 0) {
 
60
 
 
61
        if(read_cow_header(file_reader, &cow_fd, &version, &backing_file, 
 
62
                           &mtime, &size, &sectorsize, &alignment,
 
63
                           &bitmap_offset)){
 
64
                fprintf(stderr, "Reading COW header failed\n");
 
65
                exit(1);
 
66
        }
 
67
 
 
68
        if(actual_backing != NULL)
 
69
                backing_file = actual_backing;
 
70
 
 
71
        if(stat(backing_file, &buf) < 0) {
175
72
                perror("Stating backing file");
176
73
                exit(1);
177
74
        }
 
75
 
178
76
        if(buf.st_size != size){
179
77
                fprintf(stderr,"Size mismatch (%ld vs %ld) of COW header "
180
 
                        "vs backing file\n", (long int) buf.st_size, 
181
 
                        (long int) size);
 
78
                        "vs backing file \"%s\"\n", (long int) size, 
 
79
                        (long int) buf.st_size, backing_file);
182
80
                exit(1);
183
81
        }
184
82
        if(buf.st_mtime != mtime) {
185
83
                fprintf(stderr,"mtime mismatch (%ld vs %ld) of COW "
186
 
                        "header vs backing file\n", buf.st_mtime, 
187
 
                        mtime);
 
84
                        "header vs backing file \"%s\"\n", mtime, buf.st_mtime,
 
85
                        backing_file);
188
86
                exit(1);
189
87
        }
190
88
 
191
 
        if((back_fd = open(backing_file, O_RDONLY)) < 0){
 
89
        perms = (out != NULL) ? O_RDONLY : O_RDWR;
 
90
 
 
91
        if((back_fd = open(backing_file, perms)) < 0){
192
92
                perror("Opening backing file");
193
93
                exit(1);
194
94
        }
195
95
 
196
 
        sizes(size, sectorsize, bitmap_offset, &bitmap_len, &data_offset);
 
96
        if(out != NULL){
 
97
                if((out_fd = creat(out, 0644)) < 0){
 
98
                        perror("Output file open");
 
99
                        exit(1);
 
100
                }
 
101
        }
 
102
        else out_fd = back_fd;
 
103
 
 
104
        cow_sizes(version, size, sectorsize, alignment, bitmap_offset, 
 
105
                  &bitmap_len, &data_offset);
197
106
                
198
107
        bitmap = (unsigned long *) malloc(bitmap_len);
199
108
        if(bitmap == NULL) {
201
110
                exit(1);
202
111
        }
203
112
 
204
 
        if(lseek64(cow_fd, bitmap_offset, SEEK_SET) < 0){
205
 
                perror("Seeking to COW bitmap");
206
 
                exit(1);
207
 
        }
208
 
 
209
 
        if(read(cow_fd, bitmap, bitmap_len) != bitmap_len){
 
113
        if(pread(cow_fd, bitmap, bitmap_len, bitmap_offset) != bitmap_len){
210
114
                perror("Reading COW bitmap");
211
115
                exit(1);
212
116
        }
213
117
 
214
 
        blocks = bitmap_len * 8;
215
 
        block = (char *) malloc(sectorsize);
216
 
        if(block == NULL){
217
 
                perror("Malloc of buffer");
 
118
        sectors = size / sectorsize;
 
119
        sector = malloc(sectorsize);
 
120
        zeros = malloc(sectorsize);
 
121
        if((sector == NULL) || (zeros == NULL)){
 
122
                perror("Malloc of buffers");
218
123
                exit(1);
219
124
        }
220
 
        
221
 
        for(i = 0; i < blocks; i++){
 
125
 
 
126
        memset(zeros, 0, sectorsize);
 
127
 
 
128
        for(i = 0; i < sectors; i++){
222
129
                offset = i * sectorsize;
223
 
                if(ubd_test_bit(i,bitmap)){
 
130
                if(ubd_test_bit(i, bitmap)){
224
131
                        offset += data_offset;
225
132
                        in_fd = cow_fd;
226
133
                }
227
134
                else in_fd = back_fd;
228
 
                if(lseek64(in_fd, offset, SEEK_SET) < 0){
229
 
                        perror("Seeking into data");
230
 
                        exit(1);
231
 
                }
232
 
 
233
 
                if(read(in_fd, block, sectorsize) != sectorsize){
 
135
 
 
136
                /* If we're doing a destructive merge, and the backing file
 
137
                 * sector is up to date, then there's nothing to do.
 
138
                 */
 
139
                if((out_fd == back_fd) && (in_fd == back_fd))
 
140
                        continue;
 
141
 
 
142
                if(pread(in_fd, sector, sectorsize, offset) != sectorsize){
234
143
                        perror("Reading data");
235
144
                        exit(1);
236
145
                }
237
146
 
238
 
                if(write(out_fd, block, sectorsize) != sectorsize){
 
147
                /* Sparse file creation - if the sector is all zeros and it's
 
148
                 * not the last sector (which always gets written out in order
 
149
                 * to make the file size right), maybe it doesn't need to be
 
150
                 * written out.
 
151
                 */
 
152
 
 
153
                if((i < sectors - 1) && !memcmp(sector, zeros, sectorsize)){
 
154
                        /* If we're doing a non-destructive merge, then zero 
 
155
                         * sectors can just be skipped.
 
156
                         */
 
157
                        if(out_fd != back_fd)
 
158
                                continue;
 
159
 
 
160
                        /* Otherwise, we are doing a destructive merge, and
 
161
                         * we need to check the backing file for a zero
 
162
                         * sector.
 
163
                         */
 
164
                        n = pread(back_fd, sector, sectorsize, i * sectorsize);
 
165
                        if(n != sectorsize){
 
166
                                perror("Checking backing file for zeros");
 
167
                                exit(1);
 
168
                        }
 
169
 
 
170
                        if(!memcmp(sector, zeros, sectorsize))
 
171
                                continue;
 
172
 
 
173
                        /* The backing file sector isn't zeros, so the sector
 
174
                         * of zeros in the COW file needs to be written out.
 
175
                         */
 
176
                        memset(sector, 0, sectorsize);
 
177
                }
 
178
 
 
179
                /* The offset can't be 'offset' because that's used as an
 
180
                 * input offset, which may be offset by the COW header.
 
181
                 */
 
182
                n = pwrite(out_fd, sector, sectorsize, i * sectorsize);
 
183
                if(n != sectorsize){
239
184
                        perror("Writing data");
240
185
                        exit(1);
241
186
                }
242
187
        }
243
188
        free(bitmap);
244
 
        free(block);
 
189
        free(sector);
 
190
        free(zeros);
245
191
        close(cow_fd);
246
192
        close(out_fd);
247
193
        close(back_fd);
248
 
        return 0;
 
194
        return(0);
249
195
}
250
196
 
251
 
int usage(char *prog) {
252
 
        printf("%s usage:\n",prog);
253
 
        printf("%s <COW file> <new backing file>\n", prog);
254
 
        printf("creates a new filesystem image from the COW file and its.\n");
255
 
        printf("backing file.\n");
256
 
        printf("%s supports version 1 and 2 COW files.\n", prog);
257
 
        return 0;
 
197
static char *usage_string = 
 
198
"%s usage:\n"
 
199
"\t%s [ -b <actual backing file> ] <COW file> <new backing file>\n"
 
200
"\t%s [ -b <actual backing file> ] -d <COW file>\n"
 
201
"Creates a new filesystem image from the COW file and its backing file.\n"
 
202
"Specifying -d will cause a destructive, in-place merge of the COW file into\n"
 
203
"its current backing file\n"
 
204
"Specifying -b overrides the backing_file specified in the COW file.  This is\n"
 
205
"needed when dealing with a COW file that was created inside a chroot jail.\n"
 
206
"%s supports version 1 and 2 COW files.\n"
 
207
"";
 
208
 
 
209
static int Usage(char *prog) {
 
210
        fprintf(stderr, usage_string, prog, prog, prog, prog);
 
211
        exit(1);
258
212
}
259
213
    
260
214
int main(int argc, char **argv)
261
215
{
262
 
        if(argc == 3) create_backing_file(argc, argv);
263
 
        else usage(argv[0]);
 
216
        char *prog = argv[0];
 
217
        char *actual_backing_file = NULL;
 
218
        int in_place = 0;
 
219
 
 
220
        argv++;
 
221
        argc--;
 
222
 
 
223
        if(argc == 0)
 
224
                Usage(prog);
 
225
 
 
226
        if(!strcmp(argv[0], "-d")){
 
227
                in_place = 1;
 
228
                argv++;
 
229
                argc--;
 
230
        }
 
231
 
 
232
        if(!strcmp(argv[0], "-b")){
 
233
                actual_backing_file = argv[1];
 
234
                argv += 2;
 
235
                argc -= 2;
 
236
        }
 
237
 
 
238
        if(in_place){
 
239
                if(argc != 1) Usage(prog);
 
240
                create_backing_file(argv[0], NULL, actual_backing_file);
 
241
        }
 
242
        else {
 
243
                if(argc != 2) Usage(prog);
 
244
                create_backing_file(argv[0], argv[1], actual_backing_file);
 
245
        }
264
246
        return 0;
265
247
}
266
248