1/**
2 * device.c - Low level device io functions. Originated from the Linux-NTFS project.
3 *
4 * Copyright (c) 2004-2013 Anton Altaparmakov
5 * Copyright (c) 2004-2006 Szabolcs Szakacsits
6 * Copyright (c) 2010      Jean-Pierre Andre
7 * Copyright (c) 2008-2013 Tuxera Inc.
8 *
9 * This program/include file is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program/include file is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the NTFS-3G
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32#ifdef HAVE_STDLIB_H
33#include <stdlib.h>
34#endif
35#ifdef HAVE_STRING_H
36#include <string.h>
37#endif
38#ifdef HAVE_ERRNO_H
39#include <errno.h>
40#endif
41#ifdef HAVE_STDIO_H
42#include <stdio.h>
43#endif
44#ifdef HAVE_SYS_TYPES_H
45#include <sys/types.h>
46#endif
47#ifdef HAVE_SYS_STAT_H
48#include <sys/stat.h>
49#endif
50#ifdef HAVE_FCNTL_H
51#include <fcntl.h>
52#endif
53#ifdef HAVE_SYS_IOCTL_H
54#include <sys/ioctl.h>
55#endif
56#ifdef HAVE_SYS_PARAM_H
57#include <sys/param.h>
58#endif
59#ifdef HAVE_SYS_MOUNT_H
60#include <sys/mount.h>
61#endif
62#ifdef HAVE_SYS_DISK_H
63#include <sys/disk.h>
64#endif
65#ifdef HAVE_LINUX_FD_H
66#include <linux/fd.h>
67#endif
68#ifdef HAVE_LINUX_HDREG_H
69#include <linux/hdreg.h>
70#endif
71#ifdef ENABLE_HD
72#include <hd.h>
73#endif
74#ifdef __HAIKU__
75#include <Drivers.h>
76#endif
77
78#include "types.h"
79#include "mst.h"
80#include "debug.h"
81#include "device.h"
82#include "logging.h"
83#include "misc.h"
84
85#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE)
86#define BLKGETSIZE	_IO(0x12,96)  /* Get device size in 512-byte blocks. */
87#endif
88#if defined(linux) && defined(_IOR) && !defined(BLKGETSIZE64)
89#define BLKGETSIZE64	_IOR(0x12,114,size_t)	/* Get device size in bytes. */
90#endif
91#if defined(linux) && !defined(HDIO_GETGEO)
92#define HDIO_GETGEO	0x0301	/* Get device geometry. */
93#endif
94#if defined(linux) && defined(_IO) && !defined(BLKSSZGET)
95#	define BLKSSZGET _IO(0x12,104) /* Get device sector size in bytes. */
96#endif
97#if defined(linux) && defined(_IO) && !defined(BLKBSZSET)
98#	define BLKBSZSET _IOW(0x12,113,size_t) /* Set device block size in bytes. */
99#endif
100
101/**
102 * ntfs_device_alloc - allocate an ntfs device structure and pre-initialize it
103 * @name:	name of the device (must be present)
104 * @state:	initial device state (usually zero)
105 * @dops:	ntfs device operations to use with the device (must be present)
106 * @priv_data:	pointer to private data (optional)
107 *
108 * Allocate an ntfs device structure and pre-initialize it with the user-
109 * specified device operations @dops, device state @state, device name @name,
110 * and optional private data @priv_data.
111 *
112 * Note, @name is copied and can hence be freed after this functions returns.
113 *
114 * On success return a pointer to the allocated ntfs device structure and on
115 * error return NULL with errno set to the error code returned by ntfs_malloc().
116 */
117struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
118		struct ntfs_device_operations *dops, void *priv_data)
119{
120	struct ntfs_device *dev;
121
122	if (!name) {
123		errno = EINVAL;
124		return NULL;
125	}
126
127	dev = ntfs_malloc(sizeof(struct ntfs_device));
128	if (dev) {
129		if (!(dev->d_name = strdup(name))) {
130			int eo = errno;
131			free(dev);
132			errno = eo;
133			return NULL;
134		}
135		dev->d_ops = dops;
136		dev->d_state = state;
137		dev->d_private = priv_data;
138		dev->d_heads = -1;
139		dev->d_sectors_per_track = -1;
140	}
141	return dev;
142}
143
144/**
145 * ntfs_device_free - free an ntfs device structure
146 * @dev:	ntfs device structure to free
147 *
148 * Free the ntfs device structure @dev.
149 *
150 * Return 0 on success or -1 on error with errno set to the error code. The
151 * following error codes are defined:
152 *	EINVAL		Invalid pointer @dev.
153 *	EBUSY		Device is still open. Close it before freeing it!
154 */
155int ntfs_device_free(struct ntfs_device *dev)
156{
157	if (!dev) {
158		errno = EINVAL;
159		return -1;
160	}
161	if (NDevOpen(dev)) {
162		errno = EBUSY;
163		return -1;
164	}
165	free(dev->d_name);
166	free(dev);
167	return 0;
168}
169
170/*
171 *		Sync the device
172 *
173 *	returns zero if successful.
174 */
175
176int ntfs_device_sync(struct ntfs_device *dev)
177{
178	int ret;
179	struct ntfs_device_operations *dops;
180
181	if (NDevDirty(dev)) {
182		dops = dev->d_ops;
183		ret = dops->sync(dev);
184	} else
185		ret = 0;
186	return ret;
187}
188
189/**
190 * ntfs_pread - positioned read from disk
191 * @dev:	device to read from
192 * @pos:	position in device to read from
193 * @count:	number of bytes to read
194 * @b:		output data buffer
195 *
196 * This function will read @count bytes from device @dev at position @pos into
197 * the data buffer @b.
198 *
199 * On success, return the number of successfully read bytes. If this number is
200 * lower than @count this means that we have either reached end of file or
201 * encountered an error during the read so that the read is partial. 0 means
202 * end of file or nothing to read (@count is 0).
203 *
204 * On error and nothing has been read, return -1 with errno set appropriately
205 * to the return code of either seek, read, or set to EINVAL in case of
206 * invalid arguments.
207 */
208s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b)
209{
210	s64 br, total;
211	struct ntfs_device_operations *dops;
212
213	ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
214
215	if (!b || count < 0 || pos < 0) {
216		errno = EINVAL;
217		return -1;
218	}
219	if (!count)
220		return 0;
221
222	dops = dev->d_ops;
223
224	for (total = 0; count; count -= br, total += br) {
225		br = dops->pread(dev, (char*)b + total, count, pos + total);
226		/* If everything ok, continue. */
227		if (br > 0)
228			continue;
229		/* If EOF or error return number of bytes read. */
230		if (!br || total)
231			return total;
232		/* Nothing read and error, return error status. */
233		return br;
234	}
235	/* Finally, return the number of bytes read. */
236	return total;
237}
238
239/**
240 * ntfs_pwrite - positioned write to disk
241 * @dev:	device to write to
242 * @pos:	position in file descriptor to write to
243 * @count:	number of bytes to write
244 * @b:		data buffer to write to disk
245 *
246 * This function will write @count bytes from data buffer @b to the device @dev
247 * at position @pos.
248 *
249 * On success, return the number of successfully written bytes. If this number
250 * is lower than @count this means that the write has been interrupted in
251 * flight or that an error was encountered during the write so that the write
252 * is partial. 0 means nothing was written (also return 0 when @count is 0).
253 *
254 * On error and nothing has been written, return -1 with errno set
255 * appropriately to the return code of either seek, write, or set
256 * to EINVAL in case of invalid arguments.
257 */
258s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
259		const void *b)
260{
261	s64 written, total, ret = -1;
262	struct ntfs_device_operations *dops;
263
264	ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
265
266	if (!b || count < 0 || pos < 0) {
267		errno = EINVAL;
268		goto out;
269	}
270	if (!count)
271		return 0;
272	if (NDevReadOnly(dev)) {
273		errno = EROFS;
274		goto out;
275	}
276
277	dops = dev->d_ops;
278
279	NDevSetDirty(dev);
280	for (total = 0; count; count -= written, total += written) {
281		written = dops->pwrite(dev, (const char*)b + total, count,
282				       pos + total);
283		/* If everything ok, continue. */
284		if (written > 0)
285			continue;
286		/*
287		 * If nothing written or error return number of bytes written.
288		 */
289		if (!written || total)
290			break;
291		/* Nothing written and error, return error status. */
292		total = written;
293		break;
294	}
295	if (NDevSync(dev) && total && dops->sync(dev)) {
296		total--; /* on sync error, return partially written */
297	}
298	ret = total;
299out:
300	return ret;
301}
302
303/**
304 * ntfs_mst_pread - multi sector transfer (mst) positioned read
305 * @dev:	device to read from
306 * @pos:	position in file descriptor to read from
307 * @count:	number of blocks to read
308 * @bksize:	size of each block that needs mst deprotecting
309 * @b:		output data buffer
310 *
311 * Multi sector transfer (mst) positioned read. This function will read @count
312 * blocks of size @bksize bytes each from device @dev at position @pos into the
313 * the data buffer @b.
314 *
315 * On success, return the number of successfully read blocks. If this number is
316 * lower than @count this means that we have reached end of file, that the read
317 * was interrupted, or that an error was encountered during the read so that
318 * the read is partial. 0 means end of file or nothing was read (also return 0
319 * when @count or @bksize are 0).
320 *
321 * On error and nothing was read, return -1 with errno set appropriately to the
322 * return code of either seek, read, or set to EINVAL in case of invalid
323 * arguments.
324 *
325 * NOTE: If an incomplete multi sector transfer has been detected the magic
326 * will have been changed to magic_BAAD but no error will be returned. Thus it
327 * is possible that we return count blocks as being read but that any number
328 * (between zero and count!) of these blocks is actually subject to a multi
329 * sector transfer error. This should be detected by the caller by checking for
330 * the magic being "BAAD".
331 */
332s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count,
333		const u32 bksize, void *b)
334{
335	s64 br, i;
336
337	if (bksize & (bksize - 1) || bksize % NTFS_BLOCK_SIZE) {
338		errno = EINVAL;
339		return -1;
340	}
341	/* Do the read. */
342	br = ntfs_pread(dev, pos, count * bksize, b);
343	if (br < 0)
344		return br;
345	/*
346	 * Apply fixups to successfully read data, disregarding any errors
347	 * returned from the MST fixup function. This is because we want to
348	 * fixup everything possible and we rely on the fact that the "BAAD"
349	 * magic will be detected later on.
350	 */
351	count = br / bksize;
352	for (i = 0; i < count; ++i)
353		ntfs_mst_post_read_fixup((NTFS_RECORD*)
354				((u8*)b + i * bksize), bksize);
355	/* Finally, return the number of complete blocks read. */
356	return count;
357}
358
359/**
360 * ntfs_mst_pwrite - multi sector transfer (mst) positioned write
361 * @dev:	device to write to
362 * @pos:	position in file descriptor to write to
363 * @count:	number of blocks to write
364 * @bksize:	size of each block that needs mst protecting
365 * @b:		data buffer to write to disk
366 *
367 * Multi sector transfer (mst) positioned write. This function will write
368 * @count blocks of size @bksize bytes each from data buffer @b to the device
369 * @dev at position @pos.
370 *
371 * On success, return the number of successfully written blocks. If this number
372 * is lower than @count this means that the write has been interrupted or that
373 * an error was encountered during the write so that the write is partial. 0
374 * means nothing was written (also return 0 when @count or @bksize are 0).
375 *
376 * On error and nothing has been written, return -1 with errno set
377 * appropriately to the return code of either seek, write, or set
378 * to EINVAL in case of invalid arguments.
379 *
380 * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
381 * deprotect algorithm (no checking). This saves us from making a copy before
382 * the write and at the same time causes the usn to be incremented in the
383 * buffer. This conceptually fits in better with the idea that cached data is
384 * always deprotected and protection is performed when the data is actually
385 * going to hit the disk and the cache is immediately deprotected again
386 * simulating an mst read on the written data. This way cache coherency is
387 * achieved.
388 */
389s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
390		const u32 bksize, void *b)
391{
392	s64 written, i;
393
394	if (count < 0 || bksize % NTFS_BLOCK_SIZE) {
395		errno = EINVAL;
396		return -1;
397	}
398	if (!count)
399		return 0;
400	/* Prepare data for writing. */
401	for (i = 0; i < count; ++i) {
402		int err;
403
404		err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
405				((u8*)b + i * bksize), bksize);
406		if (err < 0) {
407			/* Abort write at this position. */
408			if (!i)
409				return err;
410			count = i;
411			break;
412		}
413	}
414	/* Write the prepared data. */
415	written = ntfs_pwrite(dev, pos, count * bksize, b);
416	/* Quickly deprotect the data again. */
417	for (i = 0; i < count; ++i)
418		ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)b + i * bksize));
419	if (written <= 0)
420		return written;
421	/* Finally, return the number of complete blocks written. */
422	return written / bksize;
423}
424
425/**
426 * ntfs_cluster_read - read ntfs clusters
427 * @vol:	volume to read from
428 * @lcn:	starting logical cluster number
429 * @count:	number of clusters to read
430 * @b:		output data buffer
431 *
432 * Read @count ntfs clusters starting at logical cluster number @lcn from
433 * volume @vol into buffer @b. Return number of clusters read or -1 on error,
434 * with errno set to the error code.
435 */
436s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, const s64 count,
437		void *b)
438{
439	s64 br;
440
441	if (!vol || lcn < 0 || count < 0) {
442		errno = EINVAL;
443		return -1;
444	}
445	if (vol->nr_clusters < lcn + count) {
446		errno = ESPIPE;
447		ntfs_log_perror("Trying to read outside of volume "
448				"(%lld < %lld)", (long long)vol->nr_clusters,
449			        (long long)lcn + count);
450		return -1;
451	}
452	br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits,
453			count << vol->cluster_size_bits, b);
454	if (br < 0) {
455		ntfs_log_perror("Error reading cluster(s)");
456		return br;
457	}
458	return br >> vol->cluster_size_bits;
459}
460
461/**
462 * ntfs_cluster_write - write ntfs clusters
463 * @vol:	volume to write to
464 * @lcn:	starting logical cluster number
465 * @count:	number of clusters to write
466 * @b:		data buffer to write to disk
467 *
468 * Write @count ntfs clusters starting at logical cluster number @lcn from
469 * buffer @b to volume @vol. Return the number of clusters written or -1 on
470 * error, with errno set to the error code.
471 */
472s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
473		const s64 count, const void *b)
474{
475	s64 bw;
476
477	if (!vol || lcn < 0 || count < 0) {
478		errno = EINVAL;
479		return -1;
480	}
481	if (vol->nr_clusters < lcn + count) {
482		errno = ESPIPE;
483		ntfs_log_perror("Trying to write outside of volume "
484				"(%lld < %lld)", (long long)vol->nr_clusters,
485			        (long long)lcn + count);
486		return -1;
487	}
488	if (!NVolReadOnly(vol))
489		bw = ntfs_pwrite(vol->dev, lcn << vol->cluster_size_bits,
490				count << vol->cluster_size_bits, b);
491	else
492		bw = count << vol->cluster_size_bits;
493	if (bw < 0) {
494		ntfs_log_perror("Error writing cluster(s)");
495		return bw;
496	}
497	return bw >> vol->cluster_size_bits;
498}
499
500/**
501 * ntfs_device_offset_valid - test if a device offset is valid
502 * @dev:	open device
503 * @ofs:	offset to test for validity
504 *
505 * Test if the offset @ofs is an existing location on the device described
506 * by the open device structure @dev.
507 *
508 * Return 0 if it is valid and -1 if it is not valid.
509 */
510static int ntfs_device_offset_valid(struct ntfs_device *dev, s64 ofs)
511{
512	char ch;
513
514	if (dev->d_ops->seek(dev, ofs, SEEK_SET) >= 0 &&
515			dev->d_ops->read(dev, &ch, 1) == 1)
516		return 0;
517	return -1;
518}
519
520/**
521 * ntfs_device_size_get - return the size of a device in blocks
522 * @dev:	open device
523 * @block_size:	block size in bytes in which to return the result
524 *
525 * Return the number of @block_size sized blocks in the device described by the
526 * open device @dev.
527 *
528 * Adapted from e2fsutils-1.19, Copyright (C) 1995 Theodore Ts'o.
529 *
530 * On error return -1 with errno set to the error code.
531 */
532s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size)
533{
534	s64 high, low;
535
536	if (!dev || block_size <= 0 || (block_size - 1) & block_size) {
537		errno = EINVAL;
538		return -1;
539	}
540#ifdef BLKGETSIZE64
541	{	u64 size;
542
543		if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) {
544			ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n",
545					(unsigned long long)size,
546					(unsigned long long)size);
547			return (s64)size / block_size;
548		}
549	}
550#endif
551#ifdef BLKGETSIZE
552	{	unsigned long size;
553
554		if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) {
555			ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n",
556					size, size);
557			return (s64)size * 512 / block_size;
558		}
559	}
560#endif
561#ifdef FDGETPRM
562	{       struct floppy_struct this_floppy;
563
564		if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) {
565			ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n",
566					(unsigned long)this_floppy.size,
567					(unsigned long)this_floppy.size);
568			return (s64)this_floppy.size * 512 / block_size;
569		}
570	}
571#endif
572#ifdef DIOCGMEDIASIZE
573	{
574		/* FreeBSD */
575		off_t size;
576
577		if (dev->d_ops->ioctl(dev, DIOCGMEDIASIZE, &size) >= 0) {
578			ntfs_log_debug("DIOCGMEDIASIZE nr bytes = %llu (0x%llx)\n",
579					(unsigned long long)size,
580					(unsigned long long)size);
581			return (s64)size / block_size;
582		}
583	}
584#endif
585#ifdef DKIOCGETBLOCKCOUNT
586	{
587		/* Mac OS X */
588		uint64_t blocks;
589		int sector_size;
590
591		sector_size = ntfs_device_sector_size_get(dev);
592		if (sector_size >= 0 && dev->d_ops->ioctl(dev,
593			DKIOCGETBLOCKCOUNT, &blocks) >= 0)
594		{
595			ntfs_log_debug("DKIOCGETBLOCKCOUNT nr blocks = %llu (0x%llx)\n",
596				(unsigned long long) blocks,
597				(unsigned long long) blocks);
598			return blocks * sector_size / block_size;
599		}
600	}
601#endif
602#ifdef __HAIKU__
603	{
604		off_t size = 0;
605
606		partition_info partitionInfo;
607		device_geometry geometry;
608
609		if (dev->d_ops->ioctl(dev, B_GET_PARTITION_INFO, &partitionInfo) == 0)
610			size = partitionInfo.size;
611		else if (dev->d_ops->ioctl(dev, B_GET_GEOMETRY, &geometry) == 0) {
612			size = (off_t)geometry.cylinder_count * geometry.sectors_per_track
613				* geometry.head_count * geometry.bytes_per_sector;
614		}
615
616		if (size > 0)
617			return (s64)size / block_size;
618	}
619 #endif
620
621	/*
622	 * We couldn't figure it out by using a specialized ioctl,
623	 * so do binary search to find the size of the device.
624	 */
625	low = 0LL;
626	for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1)
627		low = high;
628	while (low < high - 1LL) {
629		const s64 mid = (low + high) / 2;
630
631		if (!ntfs_device_offset_valid(dev, mid))
632			low = mid;
633		else
634			high = mid;
635	}
636	dev->d_ops->seek(dev, 0LL, SEEK_SET);
637	return (low + 1LL) / block_size;
638}
639
640/**
641 * ntfs_device_partition_start_sector_get - get starting sector of a partition
642 * @dev:	open device
643 *
644 * On success, return the starting sector of the partition @dev in the parent
645 * block device of @dev.  On error return -1 with errno set to the error code.
646 *
647 * The following error codes are defined:
648 *	EINVAL		Input parameter error
649 *	EOPNOTSUPP	System does not support HDIO_GETGEO ioctl
650 *	ENOTTY		@dev is a file or a device not supporting HDIO_GETGEO
651 */
652s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev)
653{
654	if (!dev) {
655		errno = EINVAL;
656		return -1;
657	}
658#ifdef HDIO_GETGEO
659	{	struct hd_geometry geo;
660
661		if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
662			ntfs_log_debug("HDIO_GETGEO start_sect = %lu (0x%lx)\n",
663					geo.start, geo.start);
664			return geo.start;
665		}
666	}
667#else
668	errno = EOPNOTSUPP;
669#endif
670	return -1;
671}
672
673static int ntfs_device_get_geo(struct ntfs_device *dev)
674{
675	int err;
676
677	if (!dev) {
678		errno = EINVAL;
679		return -1;
680	}
681	err = EOPNOTSUPP;
682#ifdef ENABLE_HD
683	{
684		hd_data_t *hddata;
685		hd_t *hd, *devlist, *partlist = NULL;
686		str_list_t *names;
687		hd_res_t *res;
688		const int d_name_len = strlen(dev->d_name) + 1;
689		int done = 0;
690
691		hddata = calloc(1, sizeof(*hddata));
692		if (!hddata) {
693			err = ENOMEM;
694			goto skip_hd;
695		}
696		/* List all "disk" class devices on the system. */
697		devlist = hd_list(hddata, hw_disk, 1, NULL);
698		if (!devlist) {
699			free(hddata);
700			err = ENOMEM;
701			goto skip_hd;
702		}
703		/*
704		 * Loop over each disk device looking for the device with the
705		 * same unix name as @dev.
706		 */
707		for (hd = devlist; hd; hd = hd->next) {
708			if (hd->unix_dev_name && !strncmp(dev->d_name,
709					hd->unix_dev_name, d_name_len))
710				goto got_hd;
711			if (hd->unix_dev_name2 && !strncmp(dev->d_name,
712					hd->unix_dev_name2, d_name_len))
713				goto got_hd;
714			for (names = hd->unix_dev_names; names;
715					names = names->next) {
716				if (names->str && !strncmp(dev->d_name,
717						names->str, d_name_len))
718					goto got_hd;
719			}
720		}
721		/*
722		 * Device was not a whole disk device.  Unless it is a file it
723		 * is likely to be a partition device.  List all "partition"
724		 * class devices on the system.
725		 */
726		partlist = hd_list(hddata, hw_partition, 1, NULL);
727		for (hd = partlist; hd; hd = hd->next) {
728			if (hd->unix_dev_name && !strncmp(dev->d_name,
729					hd->unix_dev_name, d_name_len))
730				goto got_part_hd;
731			if (hd->unix_dev_name2 && !strncmp(dev->d_name,
732					hd->unix_dev_name2, d_name_len))
733				goto got_part_hd;
734			for (names = hd->unix_dev_names; names;
735					names = names->next) {
736				if (names->str && !strncmp(dev->d_name,
737						names->str, d_name_len))
738					goto got_part_hd;
739			}
740		}
741		/* Failed to find the device.  Stop trying and clean up. */
742		goto end_hd;
743got_part_hd:
744		/* Get the whole block device the partition device is on. */
745		hd = hd_get_device_by_idx(hddata, hd->attached_to);
746		if (!hd)
747			goto end_hd;
748got_hd:
749		/*
750		 * @hd is now the whole block device either being formatted or
751		 * that the partition being formatted is on.
752		 *
753		 * Loop over each resource of the disk device looking for the
754		 * BIOS legacy geometry obtained from EDD which is what Windows
755		 * needs to boot.
756		 */
757		for (res = hd->res; res; res = res->next) {
758			/* geotype 3 is BIOS legacy. */
759			if (res->any.type != res_disk_geo ||
760					res->disk_geo.geotype != 3)
761				continue;
762			dev->d_heads = res->disk_geo.heads;
763			dev->d_sectors_per_track = res->disk_geo.sectors;
764			done = 1;
765		}
766end_hd:
767		if (partlist)
768			hd_free_hd_list(partlist);
769		hd_free_hd_list(devlist);
770		hd_free_hd_data(hddata);
771		free(hddata);
772		if (done) {
773			ntfs_log_debug("EDD/BIOD legacy heads = %u, sectors "
774					"per track = %u\n", dev->d_heads,
775					dev->d_sectors_per_track);
776			return 0;
777		}
778	}
779skip_hd:
780#endif
781#ifdef HDIO_GETGEO
782	{	struct hd_geometry geo;
783
784		if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) {
785			dev->d_heads = geo.heads;
786			dev->d_sectors_per_track = geo.sectors;
787			ntfs_log_debug("HDIO_GETGEO heads = %u, sectors per "
788					"track = %u\n", dev->d_heads,
789					dev->d_sectors_per_track);
790			return 0;
791		}
792		err = errno;
793	}
794#endif
795	errno = err;
796	return -1;
797}
798
799/**
800 * ntfs_device_heads_get - get number of heads of device
801 * @dev:		open device
802 *
803 * On success, return the number of heads on the device @dev.  On error return
804 * -1 with errno set to the error code.
805 *
806 * The following error codes are defined:
807 *	EINVAL		Input parameter error
808 *	EOPNOTSUPP	System does not support HDIO_GETGEO ioctl
809 *	ENOTTY		@dev is a file or a device not supporting HDIO_GETGEO
810 *	ENOMEM		Not enough memory to complete the request
811 */
812int ntfs_device_heads_get(struct ntfs_device *dev)
813{
814	if (!dev) {
815		errno = EINVAL;
816		return -1;
817	}
818	if (dev->d_heads == -1) {
819		if (ntfs_device_get_geo(dev) == -1)
820			return -1;
821		if (dev->d_heads == -1) {
822			errno = EINVAL;
823			return -1;
824		}
825	}
826	return dev->d_heads;
827}
828
829/**
830 * ntfs_device_sectors_per_track_get - get number of sectors per track of device
831 * @dev:		open device
832 *
833 * On success, return the number of sectors per track on the device @dev.  On
834 * error return -1 with errno set to the error code.
835 *
836 * The following error codes are defined:
837 *	EINVAL		Input parameter error
838 *	EOPNOTSUPP	System does not support HDIO_GETGEO ioctl
839 *	ENOTTY		@dev is a file or a device not supporting HDIO_GETGEO
840 *	ENOMEM		Not enough memory to complete the request
841 */
842int ntfs_device_sectors_per_track_get(struct ntfs_device *dev)
843{
844	if (!dev) {
845		errno = EINVAL;
846		return -1;
847	}
848	if (dev->d_sectors_per_track == -1) {
849		if (ntfs_device_get_geo(dev) == -1)
850			return -1;
851		if (dev->d_sectors_per_track == -1) {
852			errno = EINVAL;
853			return -1;
854		}
855	}
856	return dev->d_sectors_per_track;
857}
858
859/**
860 * ntfs_device_sector_size_get - get sector size of a device
861 * @dev:	open device
862 *
863 * On success, return the sector size in bytes of the device @dev.
864 * On error return -1 with errno set to the error code.
865 *
866 * The following error codes are defined:
867 *	EINVAL		Input parameter error
868 *	EOPNOTSUPP	System does not support BLKSSZGET ioctl
869 *	ENOTTY		@dev is a file or a device not supporting BLKSSZGET
870 */
871int ntfs_device_sector_size_get(struct ntfs_device *dev)
872{
873	if (!dev) {
874		errno = EINVAL;
875		return -1;
876	}
877#ifdef BLKSSZGET
878	{
879		int sect_size = 0;
880
881		if (!dev->d_ops->ioctl(dev, BLKSSZGET, &sect_size)) {
882			ntfs_log_debug("BLKSSZGET sector size = %d bytes\n",
883					sect_size);
884			return sect_size;
885		}
886	}
887#elif defined(DIOCGSECTORSIZE)
888	{
889		/* FreeBSD */
890		size_t sect_size = 0;
891
892		if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, &sect_size)) {
893			ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n",
894					(int) sect_size);
895			return sect_size;
896		}
897	}
898#elif defined(DKIOCGETBLOCKSIZE)
899	{
900		/* Mac OS X */
901		uint32_t sect_size = 0;
902
903		if (!dev->d_ops->ioctl(dev, DKIOCGETBLOCKSIZE, &sect_size)) {
904			ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n",
905					(int) sect_size);
906			return sect_size;
907		}
908	}
909#else
910	errno = EOPNOTSUPP;
911#endif
912	return -1;
913}
914
915/**
916 * ntfs_device_block_size_set - set block size of a device
917 * @dev:	open device
918 * @block_size: block size to set @dev to
919 *
920 * On success, return 0.
921 * On error return -1 with errno set to the error code.
922 *
923 * The following error codes are defined:
924 *	EINVAL		Input parameter error
925 *	EOPNOTSUPP	System does not support BLKBSZSET ioctl
926 *	ENOTTY		@dev is a file or a device not supporting BLKBSZSET
927 */
928int ntfs_device_block_size_set(struct ntfs_device *dev,
929		int block_size __attribute__((unused)))
930{
931	if (!dev) {
932		errno = EINVAL;
933		return -1;
934	}
935#ifdef BLKBSZSET
936	{
937		size_t s_block_size = block_size;
938		if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) {
939			ntfs_log_debug("Used BLKBSZSET to set block size to "
940					"%d bytes.\n", block_size);
941			return 0;
942		}
943		/* If not a block device, pretend it was successful. */
944		if (!NDevBlock(dev))
945			return 0;
946	}
947#else
948	/* If not a block device, pretend it was successful. */
949	if (!NDevBlock(dev))
950		return 0;
951	errno = EOPNOTSUPP;
952#endif
953	return -1;
954}
955