1 /////////////////////////////////////////////////////////////////////////
2 // $Id: hdimage.cc,v 1.16 2008/02/15 22:05:42 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
29 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
30 // is used to know when we are exporting symbols and when we are importing.
33 #define NO_DEVICE_INCLUDES
37 #if BX_HAVE_SYS_MMAN_H
41 #define LOG_THIS bx_devices.pluginHardDrive->
43 /*** base class device_image_t ***/
45 device_image_t::device_image_t()
50 /*** default_image_t function definitions ***/
52 int default_image_t::open(const char* pathname
)
54 return open(pathname
, O_RDWR
);
57 int default_image_t::open(const char* pathname
, int flags
)
60 HANDLE hFile
= CreateFile(pathname
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_FLAG_RANDOM_ACCESS
, NULL
);
61 if (hFile
!= INVALID_HANDLE_VALUE
) {
62 ULARGE_INTEGER FileSize
;
63 FileSize
.LowPart
= GetFileSize(hFile
, &FileSize
.HighPart
);
65 if ((FileSize
.LowPart
!= INVALID_FILE_SIZE
) || (GetLastError() == NO_ERROR
)) {
66 hd_size
= FileSize
.QuadPart
;
75 fd
= ::open(pathname
, flags
86 /* look at size of image file to calculate disk geometry */
88 int ret
= fstat(fd
, &stat_buf
);
90 BX_PANIC(("fstat() returns error!"));
92 hd_size
= (Bit64u
)stat_buf
.st_size
;
94 if ((hd_size
% 512) != 0) {
95 BX_PANIC(("size of disk image must be multiple of 512 bytes"));
101 void default_image_t::close()
108 Bit64s
default_image_t::lseek(Bit64s offset
, int whence
)
110 return (Bit64s
)::lseek(fd
, (off_t
)offset
, whence
);
113 ssize_t
default_image_t::read(void* buf
, size_t count
)
115 return ::read(fd
, (char*) buf
, count
);
118 ssize_t
default_image_t::write(const void* buf
, size_t count
)
120 return ::write(fd
, (char*) buf
, count
);
123 char increment_string(char *str
, int diff
)
125 // find the last character of the string, and increment it.
128 BX_ASSERT(p
>str
); // choke on zero length strings
129 p
--; // point to last character of the string
130 (*p
) += diff
; // increment to next/previous ascii code.
131 BX_DEBUG(("increment string returning '%s'", str
));
135 /*** concat_image_t function definitions ***/
137 concat_image_t::concat_image_t()
142 void concat_image_t::increment_string(char *str
)
144 ::increment_string(str
, +1);
147 int concat_image_t::open(const char* pathname0
)
149 char *pathname
= strdup(pathname0
);
150 BX_DEBUG(("concat_image_t.open"));
151 Bit64s start_offset
= 0;
152 for (int i
=0; i
<BX_CONCAT_MAX_IMAGES
; i
++) {
153 fd_table
[i
] = ::open(pathname
, O_RDWR
158 if (fd_table
[i
] < 0) {
160 // if no FD was opened successfully, return -1 (fail).
162 // otherwise, it only means that all images in the series have
163 // been opened. Record the number of fds opened successfully.
167 BX_DEBUG(("concat_image: open image %s, fd[%d] = %d", pathname
, i
, fd_table
[i
]));
168 /* look at size of image file to calculate disk geometry */
169 struct stat stat_buf
;
170 int ret
= fstat(fd_table
[i
], &stat_buf
);
172 BX_PANIC(("fstat() returns error!"));
175 if (S_ISBLK(stat_buf
.st_mode
)) {
176 BX_PANIC(("block devices should REALLY NOT be used as concat images"));
179 if ((stat_buf
.st_size
% 512) != 0) {
180 BX_PANIC(("size of disk image must be multiple of 512 bytes"));
182 length_table
[i
] = stat_buf
.st_size
;
183 start_offset_table
[i
] = start_offset
;
184 start_offset
+= stat_buf
.st_size
;
185 increment_string(pathname
);
187 // start up with first image selected
191 thismax
= length_table
[0]-1;
192 seek_was_last_op
= 0;
193 hd_size
= start_offset
;
194 return 0; // success.
197 void concat_image_t::close()
199 BX_DEBUG(("concat_image_t.close"));
205 Bit64s
concat_image_t::lseek(Bit64s offset
, int whence
)
207 if ((offset
% 512) != 0)
208 BX_PANIC(("lseek HD with offset not multiple of 512"));
209 BX_DEBUG(("concat_image_t.lseek(%d)", whence
));
210 // is this offset in this disk image?
211 if (offset
< thismin
) {
212 // no, look at previous images
213 for (int i
=index
-1; i
>=0; i
--) {
214 if (offset
>= start_offset_table
[i
]) {
217 thismin
= start_offset_table
[i
];
218 thismax
= thismin
+ length_table
[i
] - 1;
219 BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index
));
223 } else if (offset
> thismax
) {
224 // no, look at later images
225 for (int i
=index
+1; i
<maxfd
; i
++) {
226 if (offset
< start_offset_table
[i
] + length_table
[i
]) {
229 thismin
= start_offset_table
[i
];
230 thismax
= thismin
+ length_table
[i
] - 1;
231 BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index
));
236 // now offset should be within the current image.
237 offset
-= start_offset_table
[index
];
238 if (offset
< 0 || offset
>= length_table
[index
]) {
239 BX_PANIC(("concat_image_t.lseek to byte %ld failed", (long)offset
));
243 seek_was_last_op
= 1;
244 return (Bit64s
)::lseek(fd
, (off_t
)offset
, whence
);
247 ssize_t
concat_image_t::read(void* buf
, size_t count
)
250 BX_DEBUG(("concat_image_t.read %ld bytes", (long)count
));
251 // notice if anyone does sequential read or write without seek in between.
252 // This can be supported pretty easily, but needs additional checks for
253 // end of a partial image.
254 if (!seek_was_last_op
)
255 BX_PANIC(("no seek before read"));
256 return ::read(fd
, (char*) buf
, count
);
259 ssize_t
concat_image_t::write(const void* buf
, size_t count
)
261 BX_DEBUG(("concat_image_t.write %ld bytes", (long)count
));
262 // notice if anyone does sequential read or write without seek in between.
263 // This can be supported pretty easily, but needs additional checks for
264 // end of a partial image.
265 if (!seek_was_last_op
)
266 BX_PANIC(("no seek before write"));
267 return ::write(fd
, (char*) buf
, count
);
270 /*** sparse_image_t function definitions ***/
272 sparse_image_t::sparse_image_t ()
276 #ifdef _POSIX_MAPPED_FILES
283 void showpagetable(Bit32u * pagetable, size_t numpages)
285 printf("Non null pages: ");
286 for (int i = 0; i < numpages; i++)
288 if (pagetable[i] != 0xffffffff)
297 void sparse_image_t::read_header()
299 BX_ASSERT(sizeof(header
) == SPARSE_HEADER_SIZE
);
301 int ret
= ::read(fd
, &header
, sizeof(header
));
305 panic(strerror(errno
));
308 if (sizeof(header
) != ret
)
310 panic("could not read entire header");
313 if (dtoh32(header
.magic
) != SPARSE_HEADER_MAGIC
)
315 panic("failed header magic check");
318 if ((dtoh32(header
.version
) != SPARSE_HEADER_VERSION
) &&
319 (dtoh32(header
.version
) != SPARSE_HEADER_V1
))
321 panic("unknown version in header");
324 pagesize
= dtoh32(header
.pagesize
);
325 Bit32u numpages
= dtoh32(header
.numpages
);
327 total_size
= pagesize
;
328 total_size
*= numpages
;
331 while ((pagesize
>> pagesize_shift
) > 1) pagesize_shift
++;
333 if ((Bit32u
)(1 << pagesize_shift
) != pagesize
)
335 panic("failed block size header check");
338 pagesize_mask
= pagesize
- 1;
340 size_t preamble_size
= (sizeof(Bit32u
) * numpages
) + sizeof(header
);
342 while ((size_t)data_start
< preamble_size
) data_start
+= pagesize
;
344 bx_bool did_mmap
= 0;
346 #ifdef _POSIX_MAPPED_FILES
347 // Try to memory map from the beginning of the file (0 is trivially a page multiple)
348 void * mmap_header
= mmap(NULL
, preamble_size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
349 if (mmap_header
== MAP_FAILED
)
351 BX_INFO(("failed to mmap sparse disk file - using conventional file access"));
356 mmap_length
= preamble_size
;
358 pagetable
= ((Bit32u
*) (((Bit8u
*) mmap_header
) + sizeof(header
)));
359 system_pagesize_mask
= getpagesize() - 1;
365 pagetable
= new Bit32u
[numpages
];
367 if (pagetable
== NULL
)
369 panic("could not allocate memory for sparse disk block table");
372 ret
= ::read(fd
, pagetable
, sizeof(Bit32u
) * numpages
);
376 panic(strerror(errno
));
379 if ((int)(sizeof(Bit32u
) * numpages
) != ret
)
381 panic("could not read entire block table");
386 int sparse_image_t::open (const char* pathname0
)
388 pathname
= strdup(pathname0
);
389 BX_DEBUG(("sparse_image_t.open"));
391 fd
= ::open(pathname
, O_RDWR
399 return -1; // open failed
401 BX_DEBUG(("sparse_image: open image %s", pathname
));
405 struct stat stat_buf
;
406 if (fstat(fd
, &stat_buf
) != 0) panic(("fstat() returns error!"));
408 underlying_filesize
= stat_buf
.st_size
;
410 if ((underlying_filesize
% pagesize
) != 0)
411 panic("size of sparse disk image is not multiple of page size");
413 underlying_current_filepos
= 0;
414 if (-1 == ::lseek(fd
, 0, SEEK_SET
))
415 panic("error while seeking to start of file");
419 //showpagetable(pagetable, header.numpages);
421 char * parentpathname
= strdup(pathname
);
422 char lastchar
= ::increment_string(parentpathname
, -1);
424 if ((lastchar
>= '0') && (lastchar
<= '9'))
426 struct stat stat_buf
;
427 if (0 == stat(parentpathname
, &stat_buf
))
429 parent_image
= new sparse_image_t();
430 int ret
= parent_image
->open(parentpathname
);
431 if (ret
!= 0) return ret
;
432 if ( (parent_image
->pagesize
!= pagesize
)
433 || (parent_image
->total_size
!= total_size
))
435 panic("child drive image does not have same page count/page size configuration");
440 if (parentpathname
!= NULL
) free(parentpathname
);
442 if (dtoh32(header
.version
) == SPARSE_HEADER_VERSION
) {
443 hd_size
= dtoh64(header
.disk
);
449 void sparse_image_t::close()
451 BX_DEBUG(("concat_image_t.close"));
452 if (pathname
!= NULL
)
456 #ifdef _POSIX_MAPPED_FILES
457 if (mmap_header
!= NULL
)
459 int ret
= munmap(mmap_header
, mmap_length
);
461 BX_INFO(("failed to un-memory map sparse disk file"));
463 pagetable
= NULL
; // We didn't malloc it
468 if (pagetable
!= NULL
)
472 if (parent_image
!= NULL
)
478 Bit64s
sparse_image_t::lseek(Bit64s offset
, int whence
)
480 //showpagetable(pagetable, header.numpages);
482 if ((offset
% 512) != 0)
483 BX_PANIC(("lseek HD with offset not multiple of 512"));
484 if (whence
!= SEEK_SET
)
485 BX_PANIC(("lseek HD with whence not SEEK_SET"));
487 BX_DEBUG(("sparse_image_t.lseek(%d)", whence
));
489 if (offset
> total_size
)
491 BX_PANIC(("sparse_image_t.lseek to byte %ld failed", (long)offset
));
495 //printf("Seeking to position %ld\n", (long) offset);
497 set_virtual_page((Bit32u
)(offset
>> pagesize_shift
));
498 position_page_offset
= (Bit32u
)(offset
& pagesize_mask
);
503 inline Bit64s
sparse_image_t::get_physical_offset()
505 Bit64s physical_offset
= data_start
;
506 physical_offset
+= ((Bit64s
)position_physical_page
<< pagesize_shift
);
507 physical_offset
+= position_page_offset
;
508 return physical_offset
;
511 void sparse_image_t::set_virtual_page(Bit32u new_virtual_page
)
513 position_virtual_page
= new_virtual_page
;
514 position_physical_page
= dtoh32(pagetable
[position_virtual_page
]);
517 ssize_t
sparse_image_t::read_page_fragment(Bit32u read_virtual_page
, Bit32u read_page_offset
, size_t read_size
, void * buf
)
519 if (read_virtual_page
!= position_virtual_page
)
521 set_virtual_page(read_virtual_page
);
524 position_page_offset
= read_page_offset
;
526 if (position_physical_page
== SPARSE_PAGE_NOT_ALLOCATED
)
528 if (parent_image
!= NULL
)
530 return parent_image
->read_page_fragment(read_virtual_page
, read_page_offset
, read_size
, buf
);
534 memset(buf
, 0, read_size
);
539 Bit64s physical_offset
= get_physical_offset();
541 if (physical_offset
!= underlying_current_filepos
)
543 off_t ret
= ::lseek(fd
, (off_t
)physical_offset
, SEEK_SET
);
544 // underlying_current_filepos update deferred
546 panic(strerror(errno
));
549 //printf("Reading %s at position %ld size %d\n", pathname, (long) physical_offset, (long) read_size);
550 ssize_t readret
= ::read(fd
, buf
, read_size
);
554 panic(strerror(errno
));
557 if ((size_t)readret
!= read_size
)
559 panic("could not read block contents from file");
562 underlying_current_filepos
= physical_offset
+ read_size
;
568 ssize_t
sparse_image_t::read(void* buf
, size_t count
)
570 //showpagetable(pagetable, header.numpages);
571 ssize_t total_read
= 0;
574 BX_DEBUG(("sparse_image_t.read %ld bytes", (long)count
));
578 size_t can_read
= pagesize
- position_page_offset
;
579 if (count
< can_read
) can_read
= count
;
581 BX_ASSERT (can_read
!= 0);
583 size_t was_read
= read_page_fragment(position_virtual_page
, position_page_offset
, can_read
, buf
);
585 BX_ASSERT(was_read
== can_read
);
587 total_read
+= can_read
;
589 position_page_offset
+= can_read
;
590 if (position_page_offset
== pagesize
)
592 position_page_offset
= 0;
593 set_virtual_page(position_virtual_page
+ 1);
596 BX_ASSERT(position_page_offset
< pagesize
);
598 buf
= (((Bit8u
*) buf
) + can_read
);
605 void sparse_image_t::panic(const char * message
)
610 snprintf(buffer
, sizeof(buffer
), "error with sparse disk image %s", pathname
);
614 snprintf(buffer
, sizeof(buffer
), "error with sparse disk image %s - %s", pathname
, message
);
619 ssize_t
sparse_image_t::write (const void* buf
, size_t count
)
621 //showpagetable(pagetable, header.numpages);
623 ssize_t total_written
= 0;
625 Bit32u update_pagetable_start
= position_virtual_page
;
626 Bit32u update_pagetable_count
= 0;
629 BX_DEBUG(("sparse_image_t.write %ld bytes", (long)count
));
633 size_t can_write
= pagesize
- position_page_offset
;
634 if (count
< can_write
) can_write
= count
;
636 BX_ASSERT (can_write
!= 0);
638 if (position_physical_page
== SPARSE_PAGE_NOT_ALLOCATED
)
640 // We just add on another page at the end of the file
641 // Reclamation, compaction etc should currently be done off-line
643 Bit64s data_size
= underlying_filesize
- data_start
;
644 BX_ASSERT((data_size
% pagesize
) == 0);
646 Bit32u data_size_pages
= (Bit32u
)(data_size
/ pagesize
);
647 Bit32u next_data_page
= data_size_pages
;
649 pagetable
[position_virtual_page
] = htod32(next_data_page
);
650 position_physical_page
= next_data_page
;
652 Bit64s page_file_start
= data_start
+ ((Bit64s
)position_physical_page
<< pagesize_shift
);
654 if (parent_image
!= NULL
)
656 // If we have a parent, we must merge our portion with the parent
657 void *writebuffer
= NULL
;
659 if (can_write
== pagesize
)
661 writebuffer
= (void *) buf
;
665 writebuffer
= malloc(pagesize
);
666 if (writebuffer
== NULL
)
667 panic("Cannot allocate sufficient memory for page-merge in write");
669 // Read entire page - could optimize, but simple for now
670 parent_image
->read_page_fragment(position_virtual_page
, 0, pagesize
, writebuffer
);
672 void *dest_start
= ((Bit8u
*) writebuffer
) + position_page_offset
;
673 memcpy(dest_start
, buf
, can_write
);
676 int ret
= (int)::lseek(fd
, page_file_start
, SEEK_SET
);
677 // underlying_current_filepos update deferred
678 if (ret
== -1) panic(strerror(errno
));
680 ret
= ::write(fd
, writebuffer
, pagesize
);
681 if (ret
== -1) panic(strerror(errno
));
683 if (pagesize
!= (Bit32u
)ret
) panic("failed to write entire merged page to disk");
685 if (can_write
!= pagesize
)
692 // We need to write a zero page because read has been returning zeroes
693 // We seek as close to the page end as possible, and then write a little
694 // This produces a sparse file which has blanks
695 // Also very quick, even when pagesize is massive
696 int ret
= (int)::lseek(fd
, page_file_start
+ pagesize
- 4, SEEK_SET
);
697 // underlying_current_filepos update deferred
698 if (ret
== -1) panic(strerror(errno
));
701 ret
= ::write(fd
, &zero
, 4);
702 if (ret
== -1) panic(strerror(errno
));
704 if (ret
!= 4) panic("failed to write entire blank page to disk");
707 update_pagetable_count
= (position_virtual_page
- update_pagetable_start
) + 1;
708 underlying_filesize
= underlying_current_filepos
= page_file_start
+ pagesize
;
711 BX_ASSERT(position_physical_page
!= SPARSE_PAGE_NOT_ALLOCATED
);
713 Bit64s physical_offset
= get_physical_offset();
715 if (physical_offset
!= underlying_current_filepos
)
717 off_t ret
= ::lseek(fd
, (off_t
)physical_offset
, SEEK_SET
);
718 // underlying_current_filepos update deferred
720 panic(strerror(errno
));
723 //printf("Writing at position %ld size %d\n", (long) physical_offset, can_write);
724 ssize_t writeret
= ::write(fd
, buf
, can_write
);
728 panic(strerror(errno
));
731 if ((size_t)writeret
!= can_write
)
733 panic("could not write block contents to file");
736 underlying_current_filepos
= physical_offset
+ can_write
;
738 total_written
+= can_write
;
740 position_page_offset
+= can_write
;
741 if (position_page_offset
== pagesize
)
743 position_page_offset
= 0;
744 set_virtual_page(position_virtual_page
+ 1);
747 BX_ASSERT(position_page_offset
< pagesize
);
749 buf
= (((Bit8u
*) buf
) + can_write
);
753 if (update_pagetable_count
!= 0)
756 off_t pagetable_write_from
= sizeof(header
) + (sizeof(Bit32u
) * update_pagetable_start
);
757 size_t write_bytecount
= update_pagetable_count
* sizeof(Bit32u
);
759 #ifdef _POSIX_MAPPED_FILES
760 if (mmap_header
!= NULL
)
762 // Sync from the beginning of the page
763 size_t system_page_offset
= pagetable_write_from
& system_pagesize_mask
;
764 void *start
= ((Bit8u
*) mmap_header
+ pagetable_write_from
- system_page_offset
);
766 int ret
= msync(start
, system_page_offset
+ write_bytecount
, MS_ASYNC
);
769 panic(strerror(errno
));
777 int ret
= (int)::lseek(fd
, pagetable_write_from
, SEEK_SET
);
778 // underlying_current_filepos update deferred
779 if (ret
== -1) panic(strerror(errno
));
781 //printf("Writing header at position %ld size %ld\n", (long) pagetable_write_from, (long) write_bytecount);
782 ret
= ::write(fd
, &pagetable
[update_pagetable_start
], write_bytecount
);
783 if (ret
== -1) panic(strerror(errno
));
784 if ((size_t)ret
!= write_bytecount
) panic("could not write entire updated block header");
786 underlying_current_filepos
= pagetable_write_from
+ write_bytecount
;
790 return total_written
;
795 /*** dll_image_t function definitions ***/
798 function vdisk_open(path:PChar;numclusters,clustersize:integer):integer;
799 procedure vdisk_read(vunit:integer;blk:integer;var buf:TBlock);
800 procedure vdisk_write(vunit:integer;blk:integer;var buf:TBlock);
801 procedure vdisk_close(vunit:integer);
804 HINSTANCE hlib_vdisk
= 0;
806 int (*vdisk_open
) (const char *path
,int numclusters
,int clustersize
);
807 void (*vdisk_read
) (int vunit
,int blk
,void *buf
);
808 void (*vdisk_write
) (int vunit
,int blk
,const void *buf
);
809 void (*vdisk_close
) (int vunit
);
811 int dll_image_t::open (const char* pathname
)
813 if (hlib_vdisk
== 0) {
814 hlib_vdisk
= LoadLibrary("vdisk.dll");
815 if (hlib_vdisk
!= 0) {
816 vdisk_read
= (void (*)(int,int,void*)) GetProcAddress(hlib_vdisk
,"vdisk_read");
817 vdisk_write
= (void (*)(int,int,const void*)) GetProcAddress(hlib_vdisk
,"vdisk_write");
818 vdisk_open
= (int (*)(const char *,int,int)) GetProcAddress(hlib_vdisk
,"vdisk_open");
819 vdisk_close
= (void (*)(int)) GetProcAddress(hlib_vdisk
,"vdisk_close");
822 if (hlib_vdisk
!= 0) {
823 vunit
= vdisk_open(pathname
,0x10000,64);
831 void dll_image_t::close ()
833 if (vunit
>= 0 && hlib_vdisk
!= 0) {
838 Bit64s
dll_image_t::lseek(Bit64s offset
, int whence
)
840 vblk
= (int)(offset
>> 9);
844 ssize_t
dll_image_t::read (void* buf
, size_t count
)
846 if (vunit
>= 0 && hlib_vdisk
!= 0) {
847 vdisk_read(vunit
,vblk
,buf
);
854 ssize_t
dll_image_t::write (const void* buf
, size_t count
)
856 if (vunit
>= 0 && hlib_vdisk
!= 0) {
857 vdisk_write(vunit
,vblk
,buf
);
863 #endif // DLL_HD_SUPPORT
865 // redolog implementation
866 redolog_t::redolog_t()
871 extent_index
= (Bit32u
)0;
872 extent_offset
= (Bit32u
)0;
873 extent_next
= (Bit32u
)0;
876 void redolog_t::print_header()
878 BX_INFO(("redolog : Standard Header : magic='%s', type='%s', subtype='%s', version = %d.%d",
879 header
.standard
.magic
, header
.standard
.type
, header
.standard
.subtype
,
880 dtoh32(header
.standard
.version
)/0x10000,
881 dtoh32(header
.standard
.version
)%0x10000));
882 if (dtoh32(header
.standard
.version
) == STANDARD_HEADER_VERSION
) {
883 BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL
"d",
884 dtoh32(header
.specific
.catalog
),
885 dtoh32(header
.specific
.bitmap
),
886 dtoh32(header
.specific
.extent
),
887 dtoh64(header
.specific
.disk
)));
888 } else if (dtoh32(header
.standard
.version
) == STANDARD_HEADER_V1
) {
889 redolog_header_v1_t header_v1
;
890 memcpy(&header_v1
, &header
, STANDARD_HEADER_SIZE
);
891 BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL
"d",
892 dtoh32(header_v1
.specific
.catalog
),
893 dtoh32(header_v1
.specific
.bitmap
),
894 dtoh32(header_v1
.specific
.extent
),
895 dtoh64(header_v1
.specific
.disk
)));
899 int redolog_t::make_header(const char* type
, Bit64u size
)
901 Bit32u entries
, extent_size
, bitmap_size
;
905 // Set standard header values
906 strcpy((char*)header
.standard
.magic
, STANDARD_HEADER_MAGIC
);
907 strcpy((char*)header
.standard
.type
, REDOLOG_TYPE
);
908 strcpy((char*)header
.standard
.subtype
, type
);
909 header
.standard
.version
= htod32(STANDARD_HEADER_VERSION
);
910 header
.standard
.header
= htod32(STANDARD_HEADER_SIZE
);
915 // Compute #entries and extent size values
917 extent_size
= 8 * bitmap_size
* 512;
919 header
.specific
.catalog
= htod32(entries
);
920 header
.specific
.bitmap
= htod32(bitmap_size
);
921 header
.specific
.extent
= htod32(extent_size
);
923 maxsize
= (Bit64u
)entries
* (Bit64u
)extent_size
;
927 if(flip
&0x01) bitmap_size
*= 2;
929 } while (maxsize
< size
);
931 header
.specific
.disk
= htod64(size
);
935 catalog
= (Bit32u
*)malloc(dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
936 bitmap
= (Bit8u
*)malloc(dtoh32(header
.specific
.bitmap
));
938 if ((catalog
== NULL
) || (bitmap
==NULL
))
939 BX_PANIC(("redolog : could not malloc catalog or bitmap"));
941 for (Bit32u i
=0; i
<dtoh32(header
.specific
.catalog
); i
++)
942 catalog
[i
] = htod32(REDOLOG_PAGE_NOT_ALLOCATED
);
944 bitmap_blocs
= 1 + (dtoh32(header
.specific
.bitmap
) - 1) / 512;
945 extent_blocs
= 1 + (dtoh32(header
.specific
.extent
) - 1) / 512;
947 BX_DEBUG(("redolog : each bitmap is %d blocs", bitmap_blocs
));
948 BX_DEBUG(("redolog : each extent is %d blocs", extent_blocs
));
953 int redolog_t::create(const char* filename
, const char* type
, Bit64u size
)
955 BX_INFO(("redolog : creating redolog %s", filename
));
957 int filedes
= ::open(filename
, O_RDWR
| O_CREAT
| O_TRUNC
961 , S_IWUSR
| S_IRUSR
| S_IRGRP
| S_IWGRP
);
963 return create(filedes
, type
, size
);
966 int redolog_t::create(int filedes
, const char* type
, Bit64u size
)
972 return -1; // open failed
975 if (make_header(type
, size
) < 0)
981 ::write(fd
, &header
, dtoh32(header
.standard
.header
));
985 ::write(fd
, catalog
, dtoh32(header
.specific
.catalog
) * sizeof (Bit32u
));
990 int redolog_t::open(const char* filename
, const char *type
)
992 fd
= ::open(filename
, O_RDWR
999 BX_INFO(("redolog : could not open image %s", filename
));
1003 BX_INFO(("redolog : open image %s", filename
));
1005 int res
= ::read(fd
, &header
, sizeof(header
));
1006 if (res
!= STANDARD_HEADER_SIZE
)
1008 BX_PANIC(("redolog : could not read header"));
1014 if (strcmp((char*)header
.standard
.magic
, STANDARD_HEADER_MAGIC
) != 0)
1016 BX_PANIC(("redolog : Bad header magic"));
1020 if (strcmp((char*)header
.standard
.type
, REDOLOG_TYPE
) != 0)
1022 BX_PANIC(("redolog : Bad header type"));
1025 if (strcmp((char*)header
.standard
.subtype
, type
) != 0)
1027 BX_PANIC(("redolog : Bad header subtype"));
1031 if ((dtoh32(header
.standard
.version
) != STANDARD_HEADER_VERSION
) &&
1032 (dtoh32(header
.standard
.version
) != STANDARD_HEADER_V1
))
1034 BX_PANIC(("redolog : Bad header version"));
1038 if (dtoh32(header
.standard
.version
) == STANDARD_HEADER_V1
) {
1039 redolog_header_v1_t header_v1
;
1041 memcpy(&header_v1
, &header
, STANDARD_HEADER_SIZE
);
1042 header
.specific
.disk
= header_v1
.specific
.disk
;
1045 catalog
= (Bit32u
*)malloc(dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
1048 ::lseek(fd
,dtoh32(header
.standard
.header
),SEEK_SET
);
1049 res
= ::read(fd
, catalog
, dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
1051 if (res
!= (ssize_t
)(dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
)))
1053 BX_PANIC(("redolog : could not read catalog %d=%d",res
, dtoh32(header
.specific
.catalog
)));
1057 // check last used extent
1059 for (Bit32u i
=0; i
< dtoh32(header
.specific
.catalog
); i
++)
1061 if (dtoh32(catalog
[i
]) != REDOLOG_PAGE_NOT_ALLOCATED
)
1063 if (dtoh32(catalog
[i
]) >= extent_next
)
1064 extent_next
= dtoh32(catalog
[i
]) + 1;
1067 BX_INFO(("redolog : next extent will be at index %d",extent_next
));
1069 // memory used for storing bitmaps
1070 bitmap
= (Bit8u
*)malloc(dtoh32(header
.specific
.bitmap
));
1072 bitmap_blocs
= 1 + (dtoh32(header
.specific
.bitmap
) - 1) / 512;
1073 extent_blocs
= 1 + (dtoh32(header
.specific
.extent
) - 1) / 512;
1075 BX_DEBUG(("redolog : each bitmap is %d blocs", bitmap_blocs
));
1076 BX_DEBUG(("redolog : each extent is %d blocs", extent_blocs
));
1081 void redolog_t::close()
1086 if (catalog
!= NULL
)
1093 Bit64u
redolog_t::get_size()
1095 return dtoh64(header
.specific
.disk
);
1098 Bit64s
redolog_t::lseek(Bit64s offset
, int whence
)
1100 if ((offset
% 512) != 0) {
1101 BX_PANIC(("redolog : lseek HD with offset not multiple of 512"));
1104 if (whence
!= SEEK_SET
) {
1105 BX_PANIC(("redolog : lseek HD with whence not SEEK_SET"));
1108 if (offset
> (Bit64s
)dtoh64(header
.specific
.disk
))
1110 BX_PANIC(("redolog : lseek to byte %ld failed", (long)offset
));
1114 extent_index
= (Bit32u
)(offset
/ dtoh32(header
.specific
.extent
));
1115 extent_offset
= (Bit32u
)((offset
% dtoh32(header
.specific
.extent
)) / 512);
1117 BX_DEBUG(("redolog : lseeking extent index %d, offset %d",extent_index
, extent_offset
));
1122 ssize_t
redolog_t::read(void* buf
, size_t count
)
1124 Bit64s bloc_offset
, bitmap_offset
;
1127 BX_PANIC(("redolog : read HD with count not 512"));
1129 BX_DEBUG(("redolog : reading index %d, mapping to %d", extent_index
, dtoh32(catalog
[extent_index
])));
1131 if (dtoh32(catalog
[extent_index
]) == REDOLOG_PAGE_NOT_ALLOCATED
)
1133 // page not allocated
1137 bitmap_offset
= (Bit64s
)STANDARD_HEADER_SIZE
+ (dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
1138 bitmap_offset
+= (Bit64s
)512 * dtoh32(catalog
[extent_index
]) * (extent_blocs
+ bitmap_blocs
);
1139 bloc_offset
= bitmap_offset
+ ((Bit64s
)512 * (bitmap_blocs
+ extent_offset
));
1141 BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u
)bitmap_offset
));
1142 BX_DEBUG(("redolog : bloc offset is %x", (Bit32u
)bloc_offset
));
1144 // FIXME if same extent_index as before we can skip bitmap read
1146 ::lseek(fd
, (off_t
)bitmap_offset
, SEEK_SET
);
1148 if (::read(fd
, bitmap
, dtoh32(header
.specific
.bitmap
)) != (ssize_t
)dtoh32(header
.specific
.bitmap
))
1150 BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index
));
1154 if (((bitmap
[extent_offset
/8] >> (extent_offset
%8)) & 0x01) == 0x00)
1156 BX_DEBUG(("read not in redolog"));
1158 // bitmap says bloc not in reloglog
1162 ::lseek(fd
, (off_t
)bloc_offset
, SEEK_SET
);
1164 return (::read(fd
, buf
, count
));
1167 ssize_t
redolog_t::write(const void* buf
, size_t count
)
1170 Bit64s bloc_offset
, bitmap_offset
, catalog_offset
;
1172 bx_bool update_catalog
= 0;
1175 BX_PANIC(("redolog : write HD with count not 512"));
1177 BX_DEBUG(("redolog : writing index %d, mapping to %d", extent_index
, dtoh32(catalog
[extent_index
])));
1178 if (dtoh32(catalog
[extent_index
]) == REDOLOG_PAGE_NOT_ALLOCATED
)
1180 if (extent_next
>= dtoh32(header
.specific
.catalog
))
1182 BX_PANIC(("redolog : can't allocate new extent... catalog is full"));
1186 BX_DEBUG(("redolog : allocating new extent at %d", extent_next
));
1188 // Extent not allocated, allocate new
1189 catalog
[extent_index
] = htod32(extent_next
);
1193 char *zerobuffer
= (char*)malloc(512);
1194 memset(zerobuffer
, 0, 512);
1197 bitmap_offset
= (Bit64s
)STANDARD_HEADER_SIZE
+ (dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
1198 bitmap_offset
+= (Bit64s
)512 * dtoh32(catalog
[extent_index
]) * (extent_blocs
+ bitmap_blocs
);
1199 ::lseek(fd
, (off_t
)bitmap_offset
, SEEK_SET
);
1200 for (i
=0; i
<bitmap_blocs
; i
++)
1202 ::write(fd
, zerobuffer
, 512);
1205 for (i
=0; i
<extent_blocs
; i
++)
1207 ::write(fd
, zerobuffer
, 512);
1215 bitmap_offset
= (Bit64s
)STANDARD_HEADER_SIZE
+ (dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
1216 bitmap_offset
+= (Bit64s
)512 * dtoh32(catalog
[extent_index
]) * (extent_blocs
+ bitmap_blocs
);
1217 bloc_offset
= bitmap_offset
+ ((Bit64s
)512 * (bitmap_blocs
+ extent_offset
));
1219 BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u
)bitmap_offset
));
1220 BX_DEBUG(("redolog : bloc offset is %x", (Bit32u
)bloc_offset
));
1223 ::lseek(fd
, (off_t
)bloc_offset
, SEEK_SET
);
1224 written
= ::write(fd
, buf
, count
);
1227 // FIXME if same extent_index as before we can skip bitmap read
1228 ::lseek(fd
, (off_t
)bitmap_offset
, SEEK_SET
);
1229 if (::read(fd
, bitmap
, dtoh32(header
.specific
.bitmap
)) != (ssize_t
)dtoh32(header
.specific
.bitmap
))
1231 BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index
));
1235 // If bloc does not belong to extent yet
1236 if (((bitmap
[extent_offset
/8] >> (extent_offset
%8)) & 0x01) == 0x00)
1238 bitmap
[extent_offset
/8] |= 1 << (extent_offset
%8);
1239 ::lseek(fd
, (off_t
)bitmap_offset
, SEEK_SET
);
1240 ::write(fd
, bitmap
, dtoh32(header
.specific
.bitmap
));
1247 catalog_offset
= (Bit64s
)STANDARD_HEADER_SIZE
+ (extent_index
* sizeof(Bit32u
));
1249 BX_DEBUG(("redolog : writing catalog at offset %x", (Bit32u
)catalog_offset
));
1251 ::lseek(fd
, (off_t
)catalog_offset
, SEEK_SET
);
1252 ::write(fd
, &catalog
[extent_index
], sizeof(Bit32u
));
1258 /*** growing_image_t function definitions ***/
1260 growing_image_t::growing_image_t()
1262 redolog
= new redolog_t();
1265 growing_image_t::~growing_image_t()
1270 int growing_image_t::open(const char* pathname
)
1272 int filedes
= redolog
->open(pathname
, REDOLOG_SUBTYPE_GROWING
);
1273 hd_size
= redolog
->get_size();
1274 BX_INFO(("'growing' disk opened, growing file is '%s'", pathname
));
1278 void growing_image_t::close()
1283 Bit64s
growing_image_t::lseek(Bit64s offset
, int whence
)
1285 return redolog
->lseek(offset
, whence
);
1288 ssize_t
growing_image_t::read(void* buf
, size_t count
)
1290 memset(buf
, 0, count
);
1291 redolog
->read((char*) buf
, count
);
1295 ssize_t
growing_image_t::write(const void* buf
, size_t count
)
1297 return redolog
->write((char*) buf
, count
);
1300 /*** undoable_image_t function definitions ***/
1302 undoable_image_t::undoable_image_t(const char* _redolog_name
)
1304 redolog
= new redolog_t();
1305 ro_disk
= new default_image_t();
1306 redolog_name
= NULL
;
1307 if (_redolog_name
!= NULL
) {
1308 if (strcmp(_redolog_name
,"") != 0) {
1309 redolog_name
= strdup(_redolog_name
);
1314 undoable_image_t::~undoable_image_t()
1320 int undoable_image_t::open(const char* pathname
)
1324 if (ro_disk
->open(pathname
, O_RDONLY
)<0)
1327 hd_size
= ro_disk
->hd_size
;
1328 // if redolog name was set
1329 if (redolog_name
!= NULL
) {
1330 if (strcmp(redolog_name
, "") != 0) {
1331 logname
= (char*)malloc(strlen(redolog_name
) + 1);
1332 strcpy(logname
, redolog_name
);
1336 // Otherwise we make up the redolog filename from the pathname
1337 if (logname
== NULL
) {
1338 logname
= (char*)malloc(strlen(pathname
) + UNDOABLE_REDOLOG_EXTENSION_LENGTH
+ 1);
1339 sprintf(logname
, "%s%s", pathname
, UNDOABLE_REDOLOG_EXTENSION
);
1342 if (redolog
->open(logname
,REDOLOG_SUBTYPE_UNDOABLE
) < 0)
1344 if (redolog
->create(logname
, REDOLOG_SUBTYPE_UNDOABLE
, hd_size
) < 0)
1346 BX_PANIC(("Can't open or create redolog '%s'",logname
));
1349 if (hd_size
!= redolog
->get_size())
1351 BX_PANIC(("size reported by redolog doesn't match r/o disk size"));
1357 BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname
, logname
));
1363 void undoable_image_t::close ()
1368 if (redolog_name
!=NULL
)
1372 Bit64s
undoable_image_t::lseek(Bit64s offset
, int whence
)
1374 redolog
->lseek(offset
, whence
);
1375 return ro_disk
->lseek(offset
, whence
);
1378 ssize_t
undoable_image_t::read(void* buf
, size_t count
)
1380 // This should be fixed if count != 512
1381 if ((size_t)redolog
->read((char*) buf
, count
) != count
)
1382 return ro_disk
->read((char*) buf
, count
);
1387 ssize_t
undoable_image_t::write(const void* buf
, size_t count
)
1389 return redolog
->write((char*) buf
, count
);
1392 /*** volatile_image_t function definitions ***/
1394 volatile_image_t::volatile_image_t(const char* _redolog_name
)
1396 redolog
= new redolog_t();
1397 ro_disk
= new default_image_t();
1398 redolog_temp
= NULL
;
1399 redolog_name
= NULL
;
1400 if (_redolog_name
!= NULL
) {
1401 if (strcmp(_redolog_name
,"") != 0) {
1402 redolog_name
= strdup(_redolog_name
);
1407 volatile_image_t::~volatile_image_t()
1413 int volatile_image_t::open(const char* pathname
)
1416 const char *logname
=NULL
;
1418 if (ro_disk
->open(pathname
, O_RDONLY
)<0)
1421 hd_size
= ro_disk
->hd_size
;
1422 // if redolog name was set
1423 if (redolog_name
!= NULL
) {
1424 if (strcmp(redolog_name
, "") != 0) {
1425 logname
= redolog_name
;
1429 // otherwise use pathname as template
1430 if (logname
== NULL
) {
1434 redolog_temp
= (char*)malloc(strlen(logname
) + VOLATILE_REDOLOG_EXTENSION_LENGTH
+ 1);
1435 sprintf (redolog_temp
, "%s%s", logname
, VOLATILE_REDOLOG_EXTENSION
);
1437 filedes
= mkstemp (redolog_temp
);
1441 BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp
));
1444 if (redolog
->create(filedes
, REDOLOG_SUBTYPE_VOLATILE
, hd_size
) < 0)
1446 BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp
));
1450 #if (!defined(WIN32)) && !BX_WITH_MACOS
1451 // on unix it is legal to delete an open file
1452 unlink(redolog_temp
);
1455 BX_INFO(("'volatile' disk opened: ro-file is '%s', redolog is '%s'", pathname
, redolog_temp
));
1460 void volatile_image_t::close()
1465 #if defined(WIN32) || BX_WITH_MACOS
1466 // on non-unix we have to wait till the file is closed to delete it
1467 unlink(redolog_temp
);
1469 if (redolog_temp
!=NULL
)
1472 if (redolog_name
!=NULL
)
1476 Bit64s
volatile_image_t::lseek(Bit64s offset
, int whence
)
1478 redolog
->lseek(offset
, whence
);
1479 return ro_disk
->lseek(offset
, whence
);
1482 ssize_t
volatile_image_t::read(void* buf
, size_t count
)
1484 // This should be fixed if count != 512
1485 if ((size_t)redolog
->read((char*) buf
, count
) != count
)
1486 return ro_disk
->read((char*) buf
, count
);
1491 ssize_t
volatile_image_t::write(const void* buf
, size_t count
)
1493 return redolog
->write((char*) buf
, count
);
1496 #if BX_COMPRESSED_HD_SUPPORT
1498 /*** z_ro_image_t function definitions ***/
1500 z_ro_image_t::z_ro_image_t()
1505 int z_ro_image_t::open(const char* pathname
)
1507 fd
= ::open(pathname
, O_RDONLY
1515 BX_PANIC(("Could not open '%s' file", pathname
));
1519 gzfile
= gzdopen(fd
, "rb");
1523 void z_ro_image_t::close()
1531 Bit64s
z_ro_image_t::lseek(Bit64s _offset
, int whence
)
1533 // Only SEEK_SET supported
1534 if (whence
!= SEEK_SET
)
1536 BX_PANIC(("lseek on compressed images : only SEEK_SET supported"));
1539 // Seeking is expensive on compressed files, so we do it
1540 // only when necessary, at the latest moment
1546 ssize_t
z_ro_image_t::read(void* buf
, size_t count
)
1548 gzseek(gzfile
, offset
, SEEK_SET
);
1549 return gzread(gzfile
, buf
, count
);
1552 ssize_t
z_ro_image_t::write(const void* buf
, size_t count
)
1554 BX_PANIC(("z_ro_image: write not supported"));
1559 /*** z_undoable_image_t function definitions ***/
1561 z_undoable_image_t::z_undoable_image_t(Bit64u _size
, const char* _redolog_name
)
1563 redolog
= new redolog_t();
1564 ro_disk
= new z_ro_image_t();
1567 redolog_name
= NULL
;
1568 if (_redolog_name
!= NULL
) {
1569 if (strcmp(_redolog_name
,"") != 0) {
1570 redolog_name
= strdup(_redolog_name
);
1575 z_undoable_image_t::~z_undoable_image_t()
1581 int z_undoable_image_t::open(const char* pathname
)
1585 if (ro_disk
->open(pathname
)<0)
1588 // If redolog name was set
1589 if (redolog_name
!= NULL
) {
1590 if (strcmp(redolog_name
, "") != 0) {
1591 logname
= (char*)malloc(strlen(redolog_name
) + 1);
1592 strcpy (logname
, redolog_name
);
1596 // Otherwise we make up the redolog filename from the pathname
1597 if (logname
== NULL
) {
1598 logname
= (char*)malloc(strlen(pathname
) + UNDOABLE_REDOLOG_EXTENSION_LENGTH
+ 1);
1599 sprintf (logname
, "%s%s", pathname
, UNDOABLE_REDOLOG_EXTENSION
);
1602 if (redolog
->open(logname
, REDOLOG_SUBTYPE_UNDOABLE
) < 0)
1604 if (redolog
->create(logname
, REDOLOG_SUBTYPE_UNDOABLE
, size
) < 0)
1606 BX_PANIC(("Can't open or create redolog '%s'",logname
));
1611 BX_INFO(("'z-undoable' disk opened, z-ro-file is '%s', redolog is '%s'", pathname
, logname
));
1617 void z_undoable_image_t::close()
1622 if (redolog_name
!=NULL
)
1626 Bit64s
z_undoable_image_t::lseek(Bit64s offset
, int whence
)
1628 redolog
->lseek(offset
, whence
);
1629 return ro_disk
->lseek(offset
, whence
);
1632 ssize_t
z_undoable_image_t::read(void* buf
, size_t count
)
1634 // This should be fixed if count != 512
1635 if (redolog
->read((char*) buf
, count
) != count
)
1636 return ro_disk
->read((char*) buf
, count
);
1641 ssize_t
z_undoable_image_t::write(const void* buf
, size_t count
)
1643 return redolog
->write((char*) buf
, count
);
1647 /*** z_volatile_image_t function definitions ***/
1649 z_volatile_image_t::z_volatile_image_t(Bit64u _size
, const char* _redolog_name
)
1651 redolog
= new redolog_t();
1652 ro_disk
= new z_ro_image_t();
1655 redolog_temp
= NULL
;
1656 redolog_name
= NULL
;
1657 if (_redolog_name
!= NULL
) {
1658 if (strcmp(_redolog_name
,"") != 0) {
1659 redolog_name
= strdup(_redolog_name
);
1664 z_volatile_image_t::~z_volatile_image_t()
1670 int z_volatile_image_t::open(const char* pathname
)
1673 const char *logname
=NULL
;
1675 if (ro_disk
->open(pathname
)<0)
1678 // if redolog name was set
1679 if (redolog_name
!= NULL
) {
1680 if (strcmp(redolog_name
, "") != 0) {
1681 logname
= redolog_name
;
1685 // otherwise use pathname as template
1686 if (logname
== NULL
) {
1690 redolog_temp
= (char*)malloc(strlen(logname
) + VOLATILE_REDOLOG_EXTENSION_LENGTH
+ 1);
1691 sprintf (redolog_temp
, "%s%s", logname
, VOLATILE_REDOLOG_EXTENSION
);
1693 filedes
= mkstemp (redolog_temp
);
1697 BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp
));
1700 if (redolog
->create(filedes
, REDOLOG_SUBTYPE_VOLATILE
, size
) < 0)
1702 BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp
));
1706 #if (!defined(WIN32)) && !BX_WITH_MACOS
1707 // on unix it is legal to delete an open file
1708 unlink(redolog_temp
);
1711 BX_INFO(("'z-volatile' disk opened: z-ro-file is '%s', redolog is '%s'", pathname
, redolog_temp
));
1716 void z_volatile_image_t::close ()
1721 #if defined(WIN32) || BX_WITH_MACOS
1722 // on non-unix we have to wait till the file is closed to delete it
1723 unlink(redolog_temp
);
1726 if (redolog_temp
!=NULL
)
1729 if (redolog_name
!=NULL
)
1733 Bit64s
z_volatile_image_t::lseek(Bit64s offset
, int whence
)
1735 redolog
->lseek(offset
, whence
);
1736 return ro_disk
->lseek(offset
, whence
);
1739 ssize_t
z_volatile_image_t::read (void* buf
, size_t count
)
1741 // This should be fixed if count != 512
1742 if (redolog
->read((char*) buf
, count
) != count
)
1743 return ro_disk
->read((char*) buf
, count
);
1748 ssize_t
z_volatile_image_t::write (const void* buf
, size_t count
)
1750 return redolog
->write((char*) buf
, count
);