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 */ 117 struct 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 */ 155 int 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 176 int 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 */ 208 s64 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 */ 258 s64 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; 299 out: 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 */ 332 s64 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 */ 389 s64 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 */ 436 s64 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 */ 472 s64 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 */ 510 static 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 */ 532 s64 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 * We couldn't figure it out by using a specialized ioctl, 622 * so do binary search to find the size of the device. 623 */ 624 low = 0LL; 625 for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1) 626 low = high; 627 while (low < high - 1LL) { 628 const s64 mid = (low + high) / 2; 629 630 if (!ntfs_device_offset_valid(dev, mid)) 631 low = mid; 632 else 633 high = mid; 634 } 635 dev->d_ops->seek(dev, 0LL, SEEK_SET); 636 return (low + 1LL) / block_size; 637 } 638 639 /** 640 * ntfs_device_partition_start_sector_get - get starting sector of a partition 641 * @dev: open device 642 * 643 * On success, return the starting sector of the partition @dev in the parent 644 * block device of @dev. On error return -1 with errno set to the error code. 645 * 646 * The following error codes are defined: 647 * EINVAL Input parameter error 648 * EOPNOTSUPP System does not support HDIO_GETGEO ioctl 649 * ENOTTY @dev is a file or a device not supporting HDIO_GETGEO 650 */ 651 s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev) 652 { 653 if (!dev) { 654 errno = EINVAL; 655 return -1; 656 } 657 #ifdef HDIO_GETGEO 658 { struct hd_geometry geo; 659 660 if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) { 661 ntfs_log_debug("HDIO_GETGEO start_sect = %lu (0x%lx)\n", 662 geo.start, geo.start); 663 return geo.start; 664 } 665 } 666 #else 667 errno = EOPNOTSUPP; 668 #endif 669 return -1; 670 } 671 672 static int ntfs_device_get_geo(struct ntfs_device *dev) 673 { 674 int err; 675 676 if (!dev) { 677 errno = EINVAL; 678 return -1; 679 } 680 err = EOPNOTSUPP; 681 #ifdef ENABLE_HD 682 { 683 hd_data_t *hddata; 684 hd_t *hd, *devlist, *partlist = NULL; 685 str_list_t *names; 686 hd_res_t *res; 687 const int d_name_len = strlen(dev->d_name) + 1; 688 int done = 0; 689 690 hddata = calloc(1, sizeof(*hddata)); 691 if (!hddata) { 692 err = ENOMEM; 693 goto skip_hd; 694 } 695 /* List all "disk" class devices on the system. */ 696 devlist = hd_list(hddata, hw_disk, 1, NULL); 697 if (!devlist) { 698 free(hddata); 699 err = ENOMEM; 700 goto skip_hd; 701 } 702 /* 703 * Loop over each disk device looking for the device with the 704 * same unix name as @dev. 705 */ 706 for (hd = devlist; hd; hd = hd->next) { 707 if (hd->unix_dev_name && !strncmp(dev->d_name, 708 hd->unix_dev_name, d_name_len)) 709 goto got_hd; 710 if (hd->unix_dev_name2 && !strncmp(dev->d_name, 711 hd->unix_dev_name2, d_name_len)) 712 goto got_hd; 713 for (names = hd->unix_dev_names; names; 714 names = names->next) { 715 if (names->str && !strncmp(dev->d_name, 716 names->str, d_name_len)) 717 goto got_hd; 718 } 719 } 720 /* 721 * Device was not a whole disk device. Unless it is a file it 722 * is likely to be a partition device. List all "partition" 723 * class devices on the system. 724 */ 725 partlist = hd_list(hddata, hw_partition, 1, NULL); 726 for (hd = partlist; hd; hd = hd->next) { 727 if (hd->unix_dev_name && !strncmp(dev->d_name, 728 hd->unix_dev_name, d_name_len)) 729 goto got_part_hd; 730 if (hd->unix_dev_name2 && !strncmp(dev->d_name, 731 hd->unix_dev_name2, d_name_len)) 732 goto got_part_hd; 733 for (names = hd->unix_dev_names; names; 734 names = names->next) { 735 if (names->str && !strncmp(dev->d_name, 736 names->str, d_name_len)) 737 goto got_part_hd; 738 } 739 } 740 /* Failed to find the device. Stop trying and clean up. */ 741 goto end_hd; 742 got_part_hd: 743 /* Get the whole block device the partition device is on. */ 744 hd = hd_get_device_by_idx(hddata, hd->attached_to); 745 if (!hd) 746 goto end_hd; 747 got_hd: 748 /* 749 * @hd is now the whole block device either being formatted or 750 * that the partition being formatted is on. 751 * 752 * Loop over each resource of the disk device looking for the 753 * BIOS legacy geometry obtained from EDD which is what Windows 754 * needs to boot. 755 */ 756 for (res = hd->res; res; res = res->next) { 757 /* geotype 3 is BIOS legacy. */ 758 if (res->any.type != res_disk_geo || 759 res->disk_geo.geotype != 3) 760 continue; 761 dev->d_heads = res->disk_geo.heads; 762 dev->d_sectors_per_track = res->disk_geo.sectors; 763 done = 1; 764 } 765 end_hd: 766 if (partlist) 767 hd_free_hd_list(partlist); 768 hd_free_hd_list(devlist); 769 hd_free_hd_data(hddata); 770 free(hddata); 771 if (done) { 772 ntfs_log_debug("EDD/BIOD legacy heads = %u, sectors " 773 "per track = %u\n", dev->d_heads, 774 dev->d_sectors_per_track); 775 return 0; 776 } 777 } 778 skip_hd: 779 #endif 780 #ifdef HDIO_GETGEO 781 { struct hd_geometry geo; 782 783 if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) { 784 dev->d_heads = geo.heads; 785 dev->d_sectors_per_track = geo.sectors; 786 ntfs_log_debug("HDIO_GETGEO heads = %u, sectors per " 787 "track = %u\n", dev->d_heads, 788 dev->d_sectors_per_track); 789 return 0; 790 } 791 err = errno; 792 } 793 #endif 794 errno = err; 795 return -1; 796 } 797 798 /** 799 * ntfs_device_heads_get - get number of heads of device 800 * @dev: open device 801 * 802 * On success, return the number of heads on the device @dev. On error return 803 * -1 with errno set to the error code. 804 * 805 * The following error codes are defined: 806 * EINVAL Input parameter error 807 * EOPNOTSUPP System does not support HDIO_GETGEO ioctl 808 * ENOTTY @dev is a file or a device not supporting HDIO_GETGEO 809 * ENOMEM Not enough memory to complete the request 810 */ 811 int ntfs_device_heads_get(struct ntfs_device *dev) 812 { 813 if (!dev) { 814 errno = EINVAL; 815 return -1; 816 } 817 if (dev->d_heads == -1) { 818 if (ntfs_device_get_geo(dev) == -1) 819 return -1; 820 if (dev->d_heads == -1) { 821 errno = EINVAL; 822 return -1; 823 } 824 } 825 return dev->d_heads; 826 } 827 828 /** 829 * ntfs_device_sectors_per_track_get - get number of sectors per track of device 830 * @dev: open device 831 * 832 * On success, return the number of sectors per track on the device @dev. On 833 * error return -1 with errno set to the error code. 834 * 835 * The following error codes are defined: 836 * EINVAL Input parameter error 837 * EOPNOTSUPP System does not support HDIO_GETGEO ioctl 838 * ENOTTY @dev is a file or a device not supporting HDIO_GETGEO 839 * ENOMEM Not enough memory to complete the request 840 */ 841 int ntfs_device_sectors_per_track_get(struct ntfs_device *dev) 842 { 843 if (!dev) { 844 errno = EINVAL; 845 return -1; 846 } 847 if (dev->d_sectors_per_track == -1) { 848 if (ntfs_device_get_geo(dev) == -1) 849 return -1; 850 if (dev->d_sectors_per_track == -1) { 851 errno = EINVAL; 852 return -1; 853 } 854 } 855 return dev->d_sectors_per_track; 856 } 857 858 /** 859 * ntfs_device_sector_size_get - get sector size of a device 860 * @dev: open device 861 * 862 * On success, return the sector size in bytes of the device @dev. 863 * On error return -1 with errno set to the error code. 864 * 865 * The following error codes are defined: 866 * EINVAL Input parameter error 867 * EOPNOTSUPP System does not support BLKSSZGET ioctl 868 * ENOTTY @dev is a file or a device not supporting BLKSSZGET 869 */ 870 int ntfs_device_sector_size_get(struct ntfs_device *dev) 871 { 872 if (!dev) { 873 errno = EINVAL; 874 return -1; 875 } 876 #ifdef BLKSSZGET 877 { 878 int sect_size = 0; 879 880 if (!dev->d_ops->ioctl(dev, BLKSSZGET, §_size)) { 881 ntfs_log_debug("BLKSSZGET sector size = %d bytes\n", 882 sect_size); 883 return sect_size; 884 } 885 } 886 #elif defined(DIOCGSECTORSIZE) 887 { 888 /* FreeBSD */ 889 size_t sect_size = 0; 890 891 if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, §_size)) { 892 ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n", 893 (int) sect_size); 894 return sect_size; 895 } 896 } 897 #elif defined(DKIOCGETBLOCKSIZE) 898 { 899 /* Mac OS X */ 900 uint32_t sect_size = 0; 901 902 if (!dev->d_ops->ioctl(dev, DKIOCGETBLOCKSIZE, §_size)) { 903 ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n", 904 (int) sect_size); 905 return sect_size; 906 } 907 } 908 #else 909 errno = EOPNOTSUPP; 910 #endif 911 return -1; 912 } 913 914 /** 915 * ntfs_device_block_size_set - set block size of a device 916 * @dev: open device 917 * @block_size: block size to set @dev to 918 * 919 * On success, return 0. 920 * On error return -1 with errno set to the error code. 921 * 922 * The following error codes are defined: 923 * EINVAL Input parameter error 924 * EOPNOTSUPP System does not support BLKBSZSET ioctl 925 * ENOTTY @dev is a file or a device not supporting BLKBSZSET 926 */ 927 int ntfs_device_block_size_set(struct ntfs_device *dev, 928 int block_size __attribute__((unused))) 929 { 930 if (!dev) { 931 errno = EINVAL; 932 return -1; 933 } 934 #ifdef BLKBSZSET 935 { 936 size_t s_block_size = block_size; 937 if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) { 938 ntfs_log_debug("Used BLKBSZSET to set block size to " 939 "%d bytes.\n", block_size); 940 return 0; 941 } 942 /* If not a block device, pretend it was successful. */ 943 if (!NDevBlock(dev)) 944 return 0; 945 } 946 #else 947 /* If not a block device, pretend it was successful. */ 948 if (!NDevBlock(dev)) 949 return 0; 950 errno = EOPNOTSUPP; 951 #endif 952 return -1; 953 } 954