82 lines
3.5 KiB
C
82 lines
3.5 KiB
C
/*
|
|
|
|
File: alignio.h
|
|
|
|
Copyright (C) 2008 Christophe GRENIER <grenier@cgsecurity.org>
|
|
|
|
This software is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write the Free Software Foundation, Inc., 51
|
|
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
static int align_read(int (*fnct_read)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
|
|
disk_t *disk_car, void*buf, const unsigned int count, const uint64_t offset)
|
|
{
|
|
const uint64_t offset_new=offset+disk_car->offset;
|
|
const unsigned int count_new=((offset_new%disk_car->sector_size)+count+disk_car->sector_size-1)/disk_car->sector_size*disk_car->sector_size;
|
|
if(count!=count_new ||
|
|
((disk_car->access_mode&TESTDISK_O_DIRECT)!=0 &&
|
|
(((size_t)(buf) & (disk_car->sector_size-1))!=0) &&
|
|
(buf!=disk_car->rbuffer || disk_car->rbuffer_size<count_new))
|
|
)
|
|
{
|
|
if(disk_car->rbuffer==NULL)
|
|
disk_car->rbuffer_size=128*512;
|
|
while(disk_car->rbuffer_size < count_new)
|
|
{
|
|
free(disk_car->rbuffer);
|
|
disk_car->rbuffer=NULL;
|
|
disk_car->rbuffer_size*=2;
|
|
}
|
|
if(disk_car->rbuffer==NULL)
|
|
disk_car->rbuffer=(char*)MALLOC(disk_car->rbuffer_size);
|
|
if(fnct_read(disk_car, disk_car->rbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size)<0)
|
|
return -1;
|
|
memcpy(buf,(char*)disk_car->rbuffer+(offset_new%disk_car->sector_size),count);
|
|
return 0;
|
|
}
|
|
return fnct_read(disk_car, buf, count_new, offset_new);
|
|
}
|
|
|
|
static int align_write(int (*fnct_read)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
|
|
int (*fnct_write)(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset),
|
|
disk_t *disk_car, const void*buf, const unsigned int count, const uint64_t offset)
|
|
{
|
|
const uint64_t offset_new=offset+disk_car->offset;
|
|
const unsigned int count_new=((offset_new%disk_car->sector_size)+count+disk_car->sector_size-1)/disk_car->sector_size*disk_car->sector_size;
|
|
if(count!=count_new ||
|
|
((disk_car->access_mode&TESTDISK_O_DIRECT)!=0 &&
|
|
(((size_t)(buf) & (disk_car->sector_size-1))!=0))
|
|
)
|
|
{
|
|
if(disk_car->wbuffer==NULL)
|
|
disk_car->wbuffer_size=128*512;
|
|
while(disk_car->wbuffer_size < count_new)
|
|
{
|
|
free(disk_car->wbuffer);
|
|
disk_car->wbuffer=NULL;
|
|
disk_car->wbuffer_size*=2;
|
|
}
|
|
if(disk_car->wbuffer==NULL)
|
|
disk_car->wbuffer=(char*)MALLOC(disk_car->wbuffer_size);
|
|
if(fnct_read(disk_car, disk_car->wbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size)<0)
|
|
{
|
|
log_error("read failed but try to write anyway");
|
|
memset(disk_car->wbuffer,0, disk_car->wbuffer_size);
|
|
}
|
|
memcpy((char*)disk_car->wbuffer+(offset_new%disk_car->sector_size),buf,count);
|
|
return fnct_write(disk_car, disk_car->wbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size);
|
|
}
|
|
return fnct_write(disk_car, buf, count_new, offset_new);
|
|
}
|
|
|