summaryrefslogtreecommitdiff
path: root/support.cc
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2010-01-26 16:00:26 -0500
committersrs5694 <srs5694@users.sourceforge.net>2010-01-26 16:00:26 -0500
commit546a9c7c369df465021feecb20f6a8f81b6df6bc (patch)
tree280a7cd1fda2a5614582f8675e415d4043fe5e93 /support.cc
parentadd79a6e1b3a1af1305f02d51eb3aa148f580caa (diff)
downloadsgdisk-546a9c7c369df465021feecb20f6a8f81b6df6bc.tar.gz
New files to support disk I/O restructuring and (currently broken)
Windows version.
Diffstat (limited to 'support.cc')
-rw-r--r--support.cc290
1 files changed, 1 insertions, 289 deletions
diff --git a/support.cc b/support.cc
index 81801f3..388b71a 100644
--- a/support.cc
+++ b/support.cc
@@ -9,9 +9,8 @@
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
-#include <sys/ioctl.h>
#include <stdio.h>
-#include <string.h>
+#include <string>
#include <stdint.h>
#include <errno.h>
#include <fcntl.h>
@@ -27,10 +26,6 @@
#define BLKPBSZGET _IO(0x12,123)
#endif
-// Below constant corresponds to an 800GB disk -- a somewhat arbitrary
-// cutoff
-#define SMALLEST_ADVANCED_FORMAT UINT64_C(1677721600)
-
using namespace std;
// Get a numeric value from the user, between low and high (inclusive).
@@ -205,114 +200,6 @@ char* BytesToSI(uint64_t size, char theValue[]) {
return theValue;
} // BlocksToSI()
-// Returns block size of device pointed to by fd file descriptor. If the ioctl
-// returns an error condition, print a warning but return a value of SECTOR_SIZE
-// (512)..
-int GetBlockSize(int fd) {
- int err = -1, result;
-
-#ifdef __APPLE__
- err = ioctl(fd, DKIOCGETBLOCKSIZE, &result);
-#endif
-#ifdef __FreeBSD__
- err = ioctl(fd, DIOCGSECTORSIZE, &result);
-#endif
-#ifdef __linux__
- err = ioctl(fd, BLKSSZGET, &result);
-#endif
-
- if (err == -1) {
- result = SECTOR_SIZE;
- // ENOTTY = inappropriate ioctl; probably being called on a disk image
- // file, so don't display the warning message....
- // 32-bit code returns EINVAL, I don't know why. I know I'm treading on
- // thin ice here, but it should be OK in all but very weird cases....
- if ((errno != ENOTTY) && (errno != EINVAL)) {
- printf("\aError %d when determining sector size! Setting sector size to %d\n",
- errno, SECTOR_SIZE);
- } // if
- } // if
-
-/* if (result != 512) {
- printf("\aWARNING! Sector size is not 512 bytes! This program is likely to ");
- printf("misbehave!\nProceed at your own risk!\n\n");
- } // if */
-
- return (result);
-} // GetBlockSize()
-
-// My original FindAlignment() function (after this one) isn't working, since
-// the BLKPBSZGET ioctl() isn't doing what I expected (it returns 512 even on
-// a WD Advanced Format drive). Therefore, I'm using a simpler function that
-// returns 1-sector alignment for unusual sector sizes and drives smaller than
-// a size defined by SMALLEST_ADVANCED_FORMAT, and 8-sector alignment for
-// larger drives with 512-byte sectors.
-int FindAlignment(int fd) {
- int err, result;
-
- if ((GetBlockSize(fd) == 512) && (disksize(fd, &err) >= SMALLEST_ADVANCED_FORMAT)) {
- result = 8; // play it safe; align for 4096-byte sectors
- } else {
- result = 1; // unusual sector size; assume it's the real physical size
- } // if/else
- return result;
-} // FindAlignment
-
-// Return the partition alignment value in sectors. Right now this works
-// only for Linux 2.6.32 and later, since I can't find equivalent ioctl()s
-// for OS X or FreeBSD, and the Linux ioctl is new
-/* int FindAlignment(int fd) {
- int err = -2, errnum = 0, result = 8, physicalSectorSize = 4096;
- uint64_t diskSize;
-
- printf("Entering FindAlignment()\n");
-#if defined (__linux__) && defined (BLKPBSZGET)
- err = ioctl(fd, BLKPBSZGET, &physicalSectorSize);
- printf("In FindAlignment(), physicalSectorSize = %d, err = %d\n", physicalSectorSize, err);
-// printf("Tried to get hardware alignment; err is %d, sector size is %d\n", err, physicalSectorSize);
-#else
- err = -1;
-#endif
-
- if (err < 0) { // ioctl didn't work; have to guess....
- if (GetBlockSize(fd) == 512) {
- result = 8; // play it safe; align for 4096-byte sectors
- } else {
- result = 1; // unusual sector size; assume it's the real physical size
- } // if/else
- } else { // ioctl worked; compute alignment
- result = physicalSectorSize / GetBlockSize(fd);
- // Disks with larger physical than logical sectors must theoretically
- // have a total disk size that's a multiple of the physical sector
- // size; however, some such disks have compatibility jumper settings
- // meant for one-partition MBR setups, and these reduce the total
- // number of sectors by 1. If such a setting is used, it'll result
- // in improper alignment, so look for this condition and warn the
- // user if it's found....
- diskSize = disksize(fd, &errnum);
- if ((diskSize % (uint64_t) result) != 0) {
- fprintf(stderr, "\aWarning! Disk size (%llu) is not a multiple of alignment\n"
- "size (%d), but it should be! Check disk manual and jumper settings!\n",
- (unsigned long long) diskSize, result);
- } // if
- } // if/else
- if (result <= 0) // can happen if physical sector size < logical sector size
- result = 1;
- return result;
-} // FindAlignment(int) */
-
-// The same as FindAlignment(int), but opens and closes a device by filename
-int FindAlignment(char deviceFilename[]) {
- int fd;
- int retval = 1;
-
- if ((fd = open(deviceFilename, O_RDONLY)) != -1) {
- retval = FindAlignment(fd);
- close(fd);
- } // if
- return retval;
-} // FindAlignment(char)
-
// Return a plain-text name for a partition type.
// Convert a GUID to a string representation, suitable for display
// to humans....
@@ -463,178 +350,3 @@ uint64_t PowerOf2(int value) {
} else retval = 0;
return retval;
} // PowerOf2()
-
-// An extended file-open function. This includes some system-specific checks.
-// I want them in a function because I use these calls twice and I don't want
-// to forget to change them in one location if I need to change them in
-// the other....
-int OpenForWrite(char* deviceFilename) {
- int fd;
-
- fd = open(deviceFilename, O_WRONLY); // try to open the device; may fail....
-#ifdef __APPLE__
- // MacOS X requires a shared lock under some circumstances....
- if (fd < 0) {
- fd = open(deviceFilename, O_WRONLY|O_SHLOCK);
- } // if
-#endif
- return fd;
-} // OpenForWrite()
-
-// Resync disk caches so the OS uses the new partition table. This code varies
-// a lot from one OS to another.
-void DiskSync(int fd) {
- int i;
-
- sync();
-#ifdef __APPLE__
- printf("Warning: The kernel may continue to use old or deleted partitions.\n"
- "You should reboot or remove the drive.\n");
- /* don't know if this helps
- * it definitely will get things on disk though:
- * http://topiks.org/mac-os-x/0321278542/ch12lev1sec8.html */
- i = ioctl(fd, DKIOCSYNCHRONIZECACHE);
-#else
-#ifdef __FreeBSD__
- sleep(2);
- i = ioctl(fd, DIOCGFLUSH);
- printf("Warning: The kernel may continue to use old or deleted partitions.\n"
- "You should reboot or remove the drive.\n");
-#else
- sleep(2);
- i = ioctl(fd, BLKRRPART);
- if (i)
- printf("Warning: The kernel is still using the old partition table.\n"
- "The new table will be used at the next reboot.\n");
-#endif
-#endif
-} // DiskSync()
-
-// A variant on the standard read() function. Done to work around
-// limitations in FreeBSD concerning the matching of the sector
-// size with the number of bytes read
-int myRead(int fd, char* buffer, int numBytes) {
- int blockSize = 512, i, numBlocks, retval;
- char* tempSpace;
-
- // Compute required space and allocate memory
- blockSize = GetBlockSize(fd);
- if (numBytes <= blockSize) {
- numBlocks = 1;
- tempSpace = (char*) malloc(blockSize);
- } else {
- numBlocks = numBytes / blockSize;
- if ((numBytes % blockSize) != 0) numBlocks++;
- tempSpace = (char*) malloc(numBlocks * blockSize);
- } // if/else
-
- // Read the data into temporary space, then copy it to buffer
- retval = read(fd, tempSpace, numBlocks * blockSize);
- for (i = 0; i < numBytes; i++) {
- buffer[i] = tempSpace[i];
- } // for
-
- // Adjust the return value, if necessary....
- if (((numBlocks * blockSize) != numBytes) && (retval > 0))
- retval = numBytes;
-
- free(tempSpace);
- return retval;
-} // myRead()
-
-// A variant on the standard write() function. Done to work around
-// limitations in FreeBSD concerning the matching of the sector
-// size with the number of bytes read
-int myWrite(int fd, char* buffer, int numBytes) {
- int blockSize = 512, i, numBlocks, retval;
- char* tempSpace;
-
- // Compute required space and allocate memory
- blockSize = GetBlockSize(fd);
- if (numBytes <= blockSize) {
- numBlocks = 1;
- tempSpace = (char*) malloc(blockSize);
- } else {
- numBlocks = numBytes / blockSize;
- if ((numBytes % blockSize) != 0) numBlocks++;
- tempSpace = (char*) malloc(numBlocks * blockSize);
- } // if/else
-
- // Copy the data to my own buffer, then write it
- for (i = 0; i < numBytes; i++) {
- tempSpace[i] = buffer[i];
- } // for
- for (i = numBytes; i < numBlocks * blockSize; i++) {
- tempSpace[i] = 0;
- } // for
- retval = write(fd, tempSpace, numBlocks * blockSize);
-
- // Adjust the return value, if necessary....
- if (((numBlocks * blockSize) != numBytes) && (retval > 0))
- retval = numBytes;
-
- free(tempSpace);
- return retval;
-} // myRead()
-
-/**************************************************************************************
- * *
- * Below functions are lifted from various sources, as documented in comments before *
- * each one. *
- * *
- **************************************************************************************/
-
-// The disksize function is taken from the Linux fdisk code and modified
-// greatly since then to enable FreeBSD and MacOS support, as well as to
-// return correct values for disk image files.
-uint64_t disksize(int fd, int *err) {
- long sz; // Do not delete; needed for Linux
- long long b; // Do not delete; needed for Linux
- uint64_t sectors = 0; // size in sectors
- off_t bytes = 0; // size in bytes
- struct stat64 st;
-
- // Note to self: I recall testing a simplified version of
- // this code, similar to what's in the __APPLE__ block,
- // on Linux, but I had some problems. IIRC, it ran OK on 32-bit
- // systems but not on 64-bit. Keep this in mind in case of
- // 32/64-bit issues on MacOS....
-#ifdef __APPLE__
- *err = ioctl(fd, DKIOCGETBLOCKCOUNT, &sectors);
-#else
-#ifdef __FreeBSD__
- *err = ioctl(fd, DIOCGMEDIASIZE, &bytes);
- b = GetBlockSize(fd);
- sectors = bytes / b;
-#else
- *err = ioctl(fd, BLKGETSIZE, &sz);
- if (*err) {
- sectors = sz = 0;
- } // if
- if ((errno == EFBIG) || (!*err)) {
- *err = ioctl(fd, BLKGETSIZE64, &b);
- if (*err || b == 0 || b == sz)
- sectors = sz;
- else
- sectors = (b >> 9);
- } // if
- // Unintuitively, the above returns values in 512-byte blocks, no
- // matter what the underlying device's block size. Correct for this....
- sectors /= (GetBlockSize(fd) / 512);
-#endif
-#endif
-
- // The above methods have failed (or it's a bum filename reference),
- // so let's assume it's a regular file (a QEMU image, dd backup, or
- // what have you) and see what stat() gives us....
- if ((sectors == 0) || (*err == -1)) {
- if (fstat64(fd, &st) == 0) {
- bytes = (off_t) st.st_size;
- if ((bytes % UINT64_C(512)) != 0)
- fprintf(stderr, "Warning: File size is not a multiple of 512 bytes!"
- " Misbehavior is likely!\n\a");
- sectors = bytes / UINT64_C(512);
- } // if
- } // if
- return sectors;
-} // disksize()