1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
/*
* afflib_os.cpp:
*
* The OS-specific features of AFFLIB
*/
#include "affconfig.h"
#include "afflib.h"
#include "afflib_i.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if defined(__FreeBSD_version) && __FreeBSD_version<500000
#undef HAVE_SYS_DISK_H
#endif
#if defined(HAVE_SYS_DISK_H)
#include <sys/disk.h>
#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h> // needed for Linux
#endif
/****************************************************************
*** Extra code for Windows...
****************************************************************/
#if defined(WIN32) and !defined(__MINGW_H)
#pragma warning(disable: 4996)
int64 ftello(FILE *stream)
{
fpos_t pos;
if(fgetpos(stream,&pos) != 0){
return -1;
}
return pos;
}
int fseeko(FILE *stream,int64 offset,int whence)
{
switch(whence){
case SEEK_SET:
break; // jump down to fsetpos()
case SEEK_CUR:
offset += ftello(stream);
break;
case SEEK_END:
fseek(stream,0L,SEEK_END); // go to the end; hope this works for big files
offset = ftello(stream) - offset;
break;
default:
return -1;
}
return fsetpos(stream,&offset);
}
#endif
/****************************************************************/
/* af_figure_media():
*
* This is a function that returns, for the file handle of an open
* device, the sector_size, total_sectors, and maximum number of
* blocks that can be read at a time (or 0 if there is no max). There
* is a generic implementation at the bottom, and operating-specific
* versions above.
*/
#ifdef linux
typedef unsigned long long int u64; // required for slackware
#endif
int af_figure_media(int fd,struct af_figure_media_buf *afb)
{
memset(afb,0,sizeof(*afb));
afb->version = 1;
#ifdef __APPLE__
#define MEDIA_FIGURED
if(ioctl(fd,DKIOCGETBLOCKSIZE,&afb->sector_size)){
afb->sector_size = 512; // assume 512
}
if(ioctl(fd,DKIOCGETBLOCKCOUNT,&afb->total_sectors)){
afb->total_sectors=0; // seeking not allowed on stdin
}
if(ioctl(fd,DKIOCGETMAXBLOCKCOUNTREAD,&afb->max_read_blocks)){
afb->max_read_blocks = 0; // read all you want
}
#endif
#if defined(__FreeBSD__) && defined(DIOCGSECTORSIZE)
#define MEDIA_FIGURED
if(ioctl(fd,DIOCGSECTORSIZE,&afb->sector_size)){
afb->sector_size = 512; // can't figure it out; go with the default
}
off_t inbytes=0;
if(ioctl(fd,DIOCGMEDIASIZE,&inbytes)){
afb->total_sectors = 0;
}
if(inbytes % afb->sector_size != 0){
fprintf(stderr,"ioctl(DIOCGSECTORSIZE) returns %d bytes\n", afb->sector_size);
fprintf(stderr,"ioctl(DIOCGMEDIASIZE) returns %d bytes\n", inbytes);
fprintf(stderr,"which is not an even number of sectors.\n");
return -1;
}
afb->total_sectors = inbytes / afb->sector_size;
afb->max_read_blocks = 0;
#endif
#ifdef linux
#define MEDIA_FIGURED
/* With Linux, we figure out how many bytes there are and get sector size
* from a #define
*/
afb->sector_size = BLOCK_SIZE;
#ifdef BLKGETSIZE64
uint64_t total_bytes=0;
if(ioctl(fd,BLKGETSIZE64,&total_bytes)){
total_bytes = 0;
}
#else
int total_bytes=0;
if(ioctl(fd,BLKGETSIZE,&total_bytes)){
total_bytes = 0;
}
#endif
afb->total_sectors = total_bytes / afb->sector_size;
afb->max_read_blocks = 0;
#endif
#ifndef MEDIA_FIGURED
/* Unknown OS type. Try our best-effort guess,
*/
#ifdef BLOCK_SIZE
afb->sector_size = BLOCK_SIZE; // it's a good guess
#else
afb->sector_size = 512; // it's a good guess
#endif
/* Try seeking to the end of fd and ask where we are! */
off_t start_pos = lseek(fd,0,SEEK_CUR); // find where we are
off_t end_of_file = lseek(fd,0,SEEK_END);
if(end_of_file==-1){
end_of_file = 0; // can't figure it.
}
lseek(fd,start_pos,SEEK_SET); // go back to the starting position
afb->total_sectors = end_of_file / afb->sector_size;
afb->max_read_blocks = 0;
#endif
return 0;
}
|