summaryrefslogtreecommitdiff
path: root/diskio.cc
diff options
context:
space:
mode:
authorsrs5694 <srs5694@users.sourceforge.net>2010-01-26 15:59:58 -0500
committersrs5694 <srs5694@users.sourceforge.net>2010-01-26 15:59:58 -0500
commitadd79a6e1b3a1af1305f02d51eb3aa148f580caa (patch)
tree760dc4c9625f089621724bba5922394eb3427993 /diskio.cc
parent7dbb932233c77cc91ea202ddf5a6198034558ae2 (diff)
downloadsgdisk-add79a6e1b3a1af1305f02d51eb3aa148f580caa.tar.gz
New files to support I/O restructuring and (currently broken) Windows
version.
Diffstat (limited to 'diskio.cc')
-rw-r--r--diskio.cc164
1 files changed, 164 insertions, 0 deletions
diff --git a/diskio.cc b/diskio.cc
new file mode 100644
index 0000000..3fc3726
--- /dev/null
+++ b/diskio.cc
@@ -0,0 +1,164 @@
+//
+// C++ Interface: diskio (platform-independent components)
+//
+// Description: Class to handle low-level disk I/O for GPT fdisk
+//
+//
+// Author: Rod Smith <rodsmith@rodsbooks.com>, (C) 2009
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+// This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
+// under the terms of the GNU GPL version 2, as detailed in the COPYING file.
+
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#ifdef MINGW
+#include <windows.h>
+#include <winioctl.h>
+#define fstat64 fstat
+#define stat64 stat
+#define S_IRGRP 0
+#define S_IROTH 0
+#else
+#include <sys/ioctl.h>
+#endif
+#include <stdio.h>
+#include <string>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <iostream>
+
+#include "support.h"
+#include "diskio.h"
+
+using namespace std;
+
+DiskIO::DiskIO(void) {
+ userFilename = "";
+ realFilename = "";
+ isOpen = 0;
+ openForWrite = 0;
+ sectorData = NULL;
+} // constructor
+
+DiskIO::~DiskIO(void) {
+ Close();
+ free(sectorData);
+} // destructor
+
+// Open a disk device for reading. Returns 1 on success, 0 on failure.
+int DiskIO::OpenForRead(string filename) {
+ int shouldOpen = 1;
+
+ if (isOpen) { // file is already open
+ if (((realFilename != filename) && (userFilename != filename)) || (openForWrite)) {
+ Close();
+ } else {
+ shouldOpen = 0;
+ } // if/else
+ } // if
+
+ if (shouldOpen) {
+ userFilename = filename;
+ MakeRealName();
+ OpenForRead();
+ } // if
+
+ return isOpen;
+} // DiskIO::OpenForRead(string filename)
+
+// Open a disk for reading and writing by filename.
+// Returns 1 on success, 0 on failure.
+int DiskIO::OpenForWrite(string filename) {
+ int retval = 0;
+
+ if ((isOpen) && (openForWrite) && ((filename == realFilename) || (filename == userFilename))) {
+ retval = 1;
+ } else {
+ userFilename = filename;
+ MakeRealName();
+ retval = OpenForWrite();
+ if (retval == 0) {
+ realFilename = userFilename = "";
+ } // if
+ } // if/else
+ return retval;
+} // DiskIO::OpenForWrite(string filename)
+
+// 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 DiskIO::FindAlignment(void) {
+ int err, result;
+
+ if ((GetBlockSize() == 512) && (DiskSize(&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;
+} // DiskIO::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 DiskIO::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;
+} // DiskIO::FindAlignment(int) */
+
+// The same as FindAlignment(int), but opens and closes a device by filename
+int DiskIO::FindAlignment(string filename) {
+ int fd;
+ int retval = 1;
+
+ if (!isOpen)
+ OpenForRead(filename);
+ if (isOpen) {
+ retval = FindAlignment();
+ } // if
+ return retval;
+} // DiskIO::FindAlignment(char)