1 /*
2  * AFFLIB(tm)
3  *
4  * AFF and AFFLIB is a trademark of Simson Garfinkel and Basis Technology Corp.
5  *
6  * Distributed under the Berkeley 4-part license
7  */
8 #include "affconfig.h"
9 #include "afflib.h"
10 #include "afflib_i.h"
11 #include "vnode_split_raw.h"
12 
13 #ifdef HAVE_CTYPE_H
14 #include <ctype.h>
15 #endif
16 
17 #ifndef HAVE_ISDIGIT
isdigit(char ch)18 static int isdigit(char ch)
19 {
20     return ch>='0' && ch<='9';
21 }
22 #endif
23 
24 
25 
26 /* split raw file implementation with optional metadata support */
27 struct split_raw_private {
28     u_int   num_raw_files;	// number of raw files
29     int    *fds;		// array of file descriptors for each open raw file
30     uint64_t *pos;		// where we are in each file
31     char *first_raw_fname;    /* The filename of the first raw file. */
32     char *next_raw_fname;     /* The filename of the next raw file, or 0
33 				 when one big file is used. */
34     int64_t cur_page; // current page number, used for split_raw_get_next_seg
35 };
36 
SPLIT_RAW_PRIVATE(AFFILE * af)37 static inline struct split_raw_private *SPLIT_RAW_PRIVATE(AFFILE *af)
38 {
39     assert(af->v == &vnode_split_raw);
40     return (struct split_raw_private *)(af->vnodeprivate);
41 }
42 
43 /* Return 1 if a file is the first of a split-raw series*/
split_raw_identify_file(const char * filename,int exists)44 static int split_raw_identify_file(const char *filename,int exists)
45 {
46     if(exists && access(filename,R_OK)!=0) return 0;	// needs to exist and it doesn't
47     return af_ext_is(filename,"000") || af_ext_is(filename,"001") ||
48 	af_ext_is(filename,"aaa") || af_ext_is(filename,"AAA");
49 }
50 
51 /* split_raw_close:
52  * Close each of the split files.
53  */
54 
split_raw_close(AFFILE * af)55 static int split_raw_close(AFFILE *af)
56 {
57     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
58 
59     for (uint64_t i = 0; i < srp->num_raw_files; i++){
60 	if(srp->fds[i]){
61 	    close(srp->fds[i]);
62 	    srp->fds[i] = 0;
63 	}
64     }
65     if (srp->fds)    free (srp->fds);
66     if (srp->pos)    free (srp->pos);
67     if (srp->first_raw_fname) free (srp->first_raw_fname);
68     if (srp->next_raw_fname)  free (srp->next_raw_fname);
69     free(srp);
70     af->vnodeprivate = 0;
71     return 0;
72 }
73 
74 
75 /**
76  * increment_fname(filename):
77  * "filename.000" => "filename.001"
78  * "filename.123" => "filename.124"
79  * "filename.999" => "filename.AAA"
80  * "filename.AZZ" => "filename.BAA"
81  * "filename.aaa" => "filename.aab" (legacy support)
82  * fn must be at least 4 characters long and must have a 3-character extension
83  *
84  * @param fn filename to increment (modified in place)
85  * @return 0 if successful.
86  *         -1 for invalid filename or no more namespace.
87  */
88 /** increase the character and return true if carry */
incval(char & ch,int base)89 static bool incval(char &ch,int base)
90 {
91     if(base==10){
92 	if(ch=='9'){
93 	    ch='0';
94 	    return true;
95 	}
96 	ch++;
97 	return false;
98     }
99 
100     /* Assume base 36 */
101     switch(ch){
102     case 'Z':
103 	ch='0';				// go back to 0
104 	return true;			// and carry
105     case '9':
106 	ch='A';
107 	return false;
108     default:
109 	ch++;				// normal increment
110 	return false;
111     }
112 }
113 
split_raw_increment_fname(char * fn)114 int split_raw_increment_fname (char *fn)
115 {
116     size_t len = strlen(fn);
117     if(len<4 || fn[len-4]!='.') return -1;
118     char *ext = fn+len-3;
119 
120     /* See if it is a number */
121     if(isdigit(ext[0]) && isdigit(ext[1]) && isdigit(ext[2])){
122 	int num = atoi(ext);
123 	if(num==999){
124 	    strcpy(ext,"A00");
125 	    return 0;
126 	}
127 	snprintf(ext,4,"%03d",num+1);
128 	return 0;
129     }
130 
131     /* First digit goes A-Z, second and third go 0-9A-Z */
132 
133     /* Get the case */
134     int lower = islower(ext[0]);
135 
136     /* Convert to all uppercase */
137     for(int i=0;i<3;i++){
138 	if(isalpha(ext[i])) ext[i] = toupper(ext[i]);
139     }
140 
141     /* Increment */
142     if(incval(ext[2],10)){
143 	if(incval(ext[1],36)){
144 	    if(incval(ext[0],36)){
145 		return EINVAL;
146 	    }
147 	}
148     }
149 
150     /* Convert back to lowercase if necessary */
151     for(int i=0;i<3;i++){
152 	if(isalpha(ext[i]) && lower) ext[i] = tolower(ext[i]);
153     }
154     return 0;
155 }
156 
157 
srp_validate(AFFILE * af)158 void srp_validate(AFFILE *af)
159 {
160     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
161     for(uint32_t i=0;i<srp->num_raw_files;i++){
162 	assert(srp->fds[i]!=0);
163     }
164 }
165 
166 /** Debugging routine.
167  */
srp_dump(AFFILE * af)168 void srp_dump(AFFILE *af)
169 {
170     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
171     for(uint32_t i=0;i<srp->num_raw_files;i++){
172 	fprintf(stderr,"   fds[%d]=%d   pos[%d]=%" I64d "\n",i,srp->fds[i],i,srp->pos[i]);
173     }
174     srp_validate(af);
175     fprintf(stderr,"===================\n");
176 }
177 
srp_add_fd(AFFILE * af,int fd)178 static void srp_add_fd(AFFILE *af,int fd)
179 {
180     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
181     srp->num_raw_files++;
182     srp->fds = (int *)realloc (srp->fds, sizeof (int) * (srp->num_raw_files));
183     srp->fds[srp->num_raw_files - 1] = fd;
184     srp->pos = (uint64_t *)realloc (srp->pos, sizeof (uint64_t) * (srp->num_raw_files));
185     srp->pos[srp->num_raw_files - 1] = 0;
186 }
187 
188 
split_raw_open_internal(AFFILE * af,uint64_t * image_size)189 static int split_raw_open_internal(AFFILE *af, uint64_t *image_size)
190 {
191     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
192     int fd;
193     struct stat sb;
194 
195     fd = open(srp->first_raw_fname, af->openflags|O_BINARY, af->openmode);
196     if (fd < 0) {
197       (*af->error_reporter)("split_raw_open_internal: open(%s): ",af->fname);
198 	return -1;
199     }
200 
201     srp->num_raw_files = 1;
202     srp->fds = (int *)malloc (sizeof (int));
203     srp->fds[0] = fd;
204     srp->pos = (uint64_t *)malloc (sizeof (uint64_t));
205     if (fstat (fd, &sb) != 0) {
206       (*af->error_reporter)("split_raw_open_internal: fstat(%s): ",af->fname);
207 	close (fd);
208 	return -1;
209     }
210 
211     af->maxsize = 0;
212 
213     /* If there's a next_raw_fname set by the caller of this function, we
214      * have a split file; otherwise we have one big file.
215      */
216     if (srp->next_raw_fname==0) {
217 	(*image_size) = sb.st_size;
218 	return 0;
219     }
220 
221     /* This gets set to 1 the first time we find a file whose size doesn't
222        match the size of the first file.  If we successfully open a file
223        when this flag is already 1, then our sanity checks fail. */
224     int current_file_must_be_last = 0;
225 
226     do {
227 	if (split_raw_increment_fname (srp->next_raw_fname) != 0) {
228 	    (*af->error_reporter)("split_raw_open_internal: too many files\n");
229 	    errno = EINVAL;
230 	    return -1;
231 	}
232 	fd = open(srp->next_raw_fname,
233 		   af->openflags & O_RDWR ? (O_RDWR|O_BINARY) : (O_RDONLY|O_BINARY));
234 
235 	if (fd < 0) {
236 	    if (errno != ENOENT) {
237 		(af->error_reporter)("split_raw_open_internal errno=%d",errno);
238 		return -1;
239 	    }
240 	    (*image_size) = sb.st_size + af->maxsize * (srp->num_raw_files - 1);
241 	    errno = 0;		// reset errno
242 	    return 0;		// end of files
243 	}
244 	srp_add_fd(af,fd);
245 	if (current_file_must_be_last) {
246 	    (*af->error_reporter)("split_raw_open_internal: %s exists, "
247 				  "but previous file didn't match expected file size\n",af->fname);
248 	    return -1;
249 	}
250 	/* Set af->maxsize to the size of the first file, but only
251 	   if a second file exists.  If no second file exists, then we want
252 	   to use af->maxsize, which cannot be set until after
253 	   af_open returns.  */
254 	if (!af->maxsize)
255 	    af->maxsize = sb.st_size;
256 	if (fstat (fd, &sb) != 0) {
257 	  (*af->error_reporter)("split_raw_open_internal: fstat(%s): ",af->fname);
258 	    return -1;
259 	}
260 	if ((uint64_t)sb.st_size != af->maxsize){
261 	    current_file_must_be_last = 1;
262 	}
263     } while (1);
264     return -1;
265 }
266 
split_raw_open(AFFILE * af)267 static int split_raw_open(AFFILE *af)
268 {
269     int ret;
270 
271     af->vnodeprivate = (void *)calloc(sizeof(struct split_raw_private),1);
272     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
273 
274     srp->first_raw_fname = strdup (af->fname);
275     srp->next_raw_fname  = strdup (af->fname);
276     ret = split_raw_open_internal (af, &(af->image_size));
277 
278     if (ret != 0) {
279 	split_raw_close (af);
280 	return ret;
281     }
282 
283     /* Adaptively find the largest pagesize we can use that fits within maxsize */
284     af->image_pagesize = 512;
285     while ((af->image_pagesize < (16 * 1024 * 1024))
286 	   && !(af->maxsize % (af->image_pagesize * 2)))
287 	af->image_pagesize *= 2;
288 
289     if ((ret == 0) && (af->maxsize % af->image_pagesize!=0)) {
290 	(*af->error_reporter)("split_raw_open: %s: raw_file_size (%" I64d " not a multiple of pagesize %lu\n",
291 			      af->fname, af->maxsize,af->image_pagesize);
292 	split_raw_close (af);
293 	return -1;
294     }
295 
296     return 0;
297 }
298 
split_raw_vstat(AFFILE * af,struct af_vnode_info * vni)299 static int split_raw_vstat(AFFILE *af,struct af_vnode_info *vni)
300 {
301     memset(vni,0,sizeof(*vni));		// clear it
302     vni->imagesize = af->image_size;
303     vni->pagesize  = af->image_pagesize;
304     vni->supports_compression = 0;
305     vni->supports_metadata    = 0;
306     vni->is_raw               = 1;
307     vni->changable_pagesize   = 1;	// change it at any time
308     vni->changable_sectorsize = 1;	// change it at any time
309     return 0;
310 }
311 
split_raw_read(AFFILE * af,unsigned char * buf,uint64_t pos,size_t count)312 static int split_raw_read(AFFILE *af, unsigned char *buf, uint64_t pos,size_t count)
313 {
314     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
315     off_t c3;
316     int ret = 0;				// how many bytes read
317 
318     if ((af->image_size - pos) < (unsigned)count){
319 	count = (off_t)(af->image_size - pos);
320     }
321 
322     while (count > 0) {
323 	int filenum = -1;
324 	off_t file_offset = 0;
325 
326 	if (af->maxsize) {		// if we do file segments
327 	    filenum     = (int)(pos / af->maxsize);
328 	    file_offset = (off_t)(pos % af->maxsize);
329 	} else {
330 	    filenum     = 0;
331 	    file_offset = (off_t)pos;
332 	}
333 	if (file_offset != (off_t) srp->pos[filenum]) {
334 	    off_t c2 = lseek (srp->fds[filenum], file_offset, SEEK_SET);
335 	    if (file_offset != c2) {	// seek failed; return work to date
336 		if (ret) return ret;	// some bytes were read; return that
337 		else return -1;		// no bytes read; return error
338 	    }
339 	    srp->pos[filenum] = c2;	// this file starts here
340 	}
341 	if (af->maxsize && ((af->maxsize - file_offset) < (unsigned) count))
342 	    c3 = (off_t)(af->maxsize - file_offset);
343 	else
344 	    c3 = count;
345 	off_t c4 = read (srp->fds[filenum], buf, c3);
346 	if (c4 <= 0) {			// got an error
347 	    if (ret)	return ret;		// return how many bytes we read
348 	    else return -1;			// otherwise, return -1
349 	}
350 	buf += c4;
351 	count -= c4;
352 	ret += c4;
353 	pos += c4;
354 	srp->pos[filenum] += c4;	// position of this file pointer
355 	if (c3 != c4) return ret;		// incomplete?
356     }
357     return ret;
358 }
359 
360 /*
361  * split_raw_write_internal2:
362  * If buf==0, assume we are writing zeros to the end of the file,
363  * and just seek to the last character and write a single NUL.
364  */
365 
split_raw_write_internal2(AFFILE * af,unsigned char * buf,uint64_t pos,size_t count)366 int split_raw_write_internal2(AFFILE *af, unsigned char *buf, uint64_t pos,size_t count)
367 {
368     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
369     off_t c1, c3;
370     int i;
371     int ret = 0;
372     struct affcallback_info acbi;
373 
374     /* Setup the callback structure */
375     memset(&acbi,0,sizeof(acbi));
376     acbi.info_version = 1;
377     acbi.af = af->parent ? af->parent : af;
378     acbi.pagenum = af->image_pagesize ? pos / af->image_pagesize : 0;
379     acbi.bytes_to_write = count;
380 
381     while (count > 0) {
382 	if (af->maxsize) {	// do we need to possibly split into multiple file writes?
383 	    /* Figure out which file number we will need to write to... */
384 	    if (pos >= (af->maxsize * srp->num_raw_files)) {
385 		int fd = open(srp->next_raw_fname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, af->openmode);
386 		if (fd < 0) {
387 		  (*af->error_reporter)("split_raw_write: open(%s): ",af->fname);
388 		    if (ret) return ret;
389 		    else return -1;
390 		}
391 		srp_add_fd(af,fd);
392 		if (split_raw_increment_fname (srp->next_raw_fname) != 0) {
393 		  (*af->error_reporter)("split_raw_write: too many files\n");
394 		    if (ret)
395 			return ret;
396 		    else
397 			return -1;
398 		}
399 	    }
400 	    i  = (int)(pos / af->maxsize);
401 	    c1 = (off_t)(pos % af->maxsize);
402 	} else {
403 	    i = 0;
404 	    c1 = (off_t)pos;
405 	}
406 	if (c1 != (off_t)srp->pos[i]) {	// do we need to seek this file?
407 	    off_t c2 = lseek (srp->fds[i], c1, SEEK_SET); // try to seek
408 	    if (c1 != c2) {		// hm. Ended up in the wrong place. That's an error
409 		if (ret>0) {		// return how many bytes we got
410 		    return ret;
411 		}
412 		else {
413 		    return -1;
414 		}
415 	    }
416 	    srp->pos[i] = c2;
417 	}
418 	if (af->maxsize && ((af->maxsize - c1) < (unsigned)count))
419 	  c3 = (off_t)(af->maxsize - c1);
420 	else
421 	    c3 = count;
422 	if(af->w_callback) {acbi.phase = 3;(*af->w_callback)(&acbi);}
423 
424 	/* WRITE THE DATA! */
425 	off_t c4 = 0;
426 
427 	if(buf){
428 	    c4 = write (srp->fds[i], buf, c3);
429 	}
430 	else {
431 	    /* Extend with lseek() and write a single byte */
432 	    char z = 0;
433 
434 	    lseek(srp->fds[i],c3-1,SEEK_CUR);
435 	    if(write(srp->fds[i],&z,1)!=1) return -1; // failure
436 	    c4 = c3;
437 	}
438 
439 	/* DONE! */
440 
441 	acbi.bytes_written = c4;
442 	if(af->w_callback) {acbi.phase = 4;(*af->w_callback)(&acbi);}
443 	if (c4 <= 0) {			// some error writing?
444 	    if (ret)
445 		return ret;
446 	    else
447 		return -1;
448 	}
449 	buf   += c4;
450 	count -= c4;
451 	ret   += c4;
452 	pos   += c4;
453 	srp->pos[i] += c4;
454 	if (af->image_size < pos) af->image_size = pos;	// image was extended
455 	if (c3 != c4){			// amount written doesn't equal request; return
456 	    return ret;
457 	}
458     }
459     return ret;
460 }
461 
split_raw_write(AFFILE * af,unsigned char * buf,uint64_t pos,size_t count)462 int split_raw_write(AFFILE *af, unsigned char *buf, uint64_t pos,size_t count)
463 {
464   /* If we are being asked to start writing beyond the end of the file
465    * pad out the file (and possibly create one or more new image files.)
466    */
467 
468   if (af->maxsize) {
469       if (pos > af->image_size) {        // writing beyond the end...
470 	  while(pos > af->image_size){
471 
472 	      /* repeat until file is as big as where we should be writing */
473 	      int64_t bytes_left   = pos - af->image_size;
474 	      int bytes_to_write = (int)(af->maxsize - (af->image_size % af->maxsize));
475 	      if(bytes_to_write > bytes_left) bytes_to_write = (int)bytes_left;
476 	      int bytes_written = split_raw_write_internal2(af,0,af->image_size,bytes_to_write);
477 	      if(bytes_to_write != bytes_written){
478 		  return -1;		// some kind of internal error
479 	      }
480 	  }
481       }
482   }
483 
484   return split_raw_write_internal2 (af, buf, pos,count);
485 }
486 
487 
488 
489 /* Get a segment; if a data page is being asked for, then fake it.
490  * Otherwise, return an error.
491  */
492 
split_raw_get_seg(AFFILE * af,const char * name,uint32_t * arg,unsigned char * data,size_t * datalen)493 static int split_raw_get_seg(AFFILE *af,const char *name,uint32_t *arg,unsigned char *data,
494 		       size_t *datalen)
495 {
496     int64_t page_num = af_segname_page_number(name);
497     if(page_num<0){
498 	/* See if PAGESIZE or IMAGESIZE is being requested; we can fake those */
499 	if(strcmp(name,AF_PAGESIZE)==0){
500 	    if(arg) *arg = af->image_pagesize;
501 	    if(datalen) *datalen = 0;
502 	    return 0;
503 	}
504 	if(strcmp(name,AF_IMAGESIZE)==0){
505 	    struct aff_quad q;
506 	    if(data && *datalen>=8){
507 		q.low = htonl((uint32_t)(af->image_size & 0xffffffff));
508 		q.high = htonl((uint32_t)(af->image_size >> 32));
509 		memcpy(data,&q,8);
510 		*datalen = 8;
511 	    }
512 	    return 0;
513 	}
514 	if(strcmp(name,AF_SECTORSIZE)==0){
515 	    if(arg) *arg = af->image_sectorsize;
516 	    if(datalen) *datalen = 0;
517 	    return 0;
518 	}
519 	if(strcmp(name,AF_DEVICE_SECTORS)==0){
520 	    int64_t devicesectors = af->image_size / af->image_sectorsize;
521 	    struct aff_quad q;
522 	    if(data && *datalen>=8){
523 		q.low = htonl((uint32_t)(devicesectors & 0xffffffff));
524 		q.high = htonl((uint32_t)(devicesectors >> 32));
525 		memcpy(data,&q,8);
526 		*datalen = 8;
527 	    }
528 	    return 0;
529 	}
530 	errno = ENOTSUP;		// sorry! We don't store metadata
531 	return -1;
532     }
533 
534     uint64_t pos = page_num * af->image_pagesize; // where we are to start reading
535     uint64_t bytes_left = af->image_size - pos;	// how many bytes left in the file
536 
537     uint32_t bytes_to_read = af->image_pagesize; // copy this many bytes, unless
538     if(bytes_to_read > bytes_left) bytes_to_read = (uint32_t)bytes_left; // only this much is left
539 
540     if(arg) *arg = 0;			// arg is always 0
541     if(datalen){
542 	if(data==0){ // asked for 0 bytes, so give the actual size
543 	    *datalen = bytes_to_read;
544 	    return 0;
545 	}
546 	if(*datalen < (unsigned)bytes_to_read){
547 	    *datalen = bytes_to_read;
548 	    return AF_ERROR_DATASMALL;
549 	}
550     }
551     if(data){
552 	int bytes_read = split_raw_read(af,data,pos,bytes_to_read);
553 	if(bytes_read>=0){
554 	    if(datalen) *datalen = bytes_read;
555 	    return 0;
556 	}
557 	return -1;			// some kind of EOF?
558     }
559     return 0;				// no problems!
560 }
561 
562 /*
563  * split_raw_get_next_seg:
564  * Try get_next_seg on the AFF file first. If that fails,
565  * create the next virtual segment
566  */
567 
split_raw_get_next_seg(AFFILE * af,char * segname,size_t segname_len,uint32_t * arg,unsigned char * data,size_t * datalen_)568 static int split_raw_get_next_seg(AFFILE *af,char *segname,size_t segname_len,uint32_t *arg,
569 				  unsigned char *data,size_t *datalen_)
570 {
571     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
572 
573     int64_t total_pages = (af->image_size + af->image_pagesize - 1) / af->image_pagesize;
574     if(srp->cur_page >= total_pages) return -1; // that's all there are
575 
576     /* Make the segment name */
577     char pagename[AF_MAX_NAME_LEN];
578     memset(pagename,0,sizeof(pagename));
579     snprintf(pagename,sizeof(pagename),AF_PAGE,srp->cur_page++);
580 
581     /* Get the segment, if we can */
582     int r = split_raw_get_seg(af,pagename,arg,data,datalen_);
583 
584     /* If r==0 and there is room for copying in the segment name, return it */
585     if(r==0){
586 	if(strlen(pagename)+1 < segname_len){
587 	    strcpy(segname,pagename);
588 	    return 0;
589 	}
590 	/* segname wasn't big enough */
591 	return -2;
592     }
593     return r;				// some other error
594 }
595 
596 
597 /* Rewind all of the segments */
split_raw_rewind_seg(AFFILE * af)598 static int split_raw_rewind_seg(AFFILE *af)
599 {
600     struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af);
601     srp->cur_page = 0;
602     return 0;
603 }
604 
split_raw_update_seg(AFFILE * af,const char * name,uint32_t,const u_char * value,uint32_t vallen)605 static int split_raw_update_seg(AFFILE *af, const char *name,
606                                 uint32_t /*arg*/,const u_char *value,uint32_t vallen)
607 
608 {
609     int64_t page_num = af_segname_page_number(name);
610     if(page_num<0){
611 	errno = ENOTSUP;		// sorry! We don't store metadata
612 	return -1;
613     }
614 
615     uint64_t pos = page_num * af->image_pagesize; // where we are to start reading
616     int written = split_raw_write(af, (unsigned char *)value, pos,vallen);
617     if(written==(int)vallen) return 0;	// success
618     return -1;
619 }
620 
621 
622 struct af_vnode vnode_split_raw = {
623     AF_IDENTIFY_SPLIT_RAW,
624     AF_VNODE_TYPE_COMPOUND|AF_VNODE_TYPE_RELIABLE|AF_VNODE_MAXSIZE_MULTIPLE|AF_VNODE_NO_SIGNING|AF_VNODE_NO_SEALING,
625     "Split Raw",
626     split_raw_identify_file,
627     split_raw_open,
628     split_raw_close,
629     split_raw_vstat,
630     split_raw_get_seg,			// get seg
631     split_raw_get_next_seg,		// get_next_seg
632     split_raw_rewind_seg,		// rewind_seg
633     split_raw_update_seg,		// update_seg
634     0,					// del_seg
635     split_raw_read,			// read
636     split_raw_write			// write
637 };
638 
639 
640