| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #if defined __linux__ || defined __CYGWIN__ |
| #include <ctype.h> |
| #endif |
| |
| #include "blkdev.h" |
| #include "wholedisk.h" |
| |
| int is_whole_disk_fd(int fd, const char *name) |
| { |
| #ifdef HDIO_GETGEO |
| struct hd_geometry geometry; |
| int i = 0; |
| |
| if (fd != -1) |
| i = ioctl(fd, HDIO_GETGEO, &geometry); |
| if (i == 0) |
| return geometry.start == 0; |
| #endif |
| /* |
| * The "silly heuristic" is still sexy for us, because |
| * for example Xen doesn't implement HDIO_GETGEO for virtual |
| * block devices (/dev/xvda). |
| * |
| * -- kzak@redhat.com (23-Feb-2006) |
| */ |
| size_t len = strlen(name); |
| if(len < 2) return 1; |
| name += len; |
| #if defined __linux__ || defined __CYGWIN__ |
| return !isdigit(name[-1]) || name[-2] != 'p'; |
| #elif defined __SVR4 |
| #if defined __sun && defined __sparc |
| return name[-2] == 's' && name[-1] == '2'; |
| #else |
| return name[-2] == 'p' && name[-1] == '0'; |
| #endif |
| #else |
| // BSD or GNU/Hurd |
| return name[-2] != 'p' && name[-2] != 's'; |
| #endif |
| } |
| |
| int is_whole_disk(const char *name) |
| { |
| int fd = -1, res = 0; |
| #ifdef HDIO_GETGEO |
| fd = open(name, O_RDONLY); |
| if (fd != -1) |
| #endif |
| res = is_whole_disk_fd(fd, name); |
| |
| if (fd != -1) |
| close(fd); |
| return res; |
| } |
| |
| #ifdef TEST_PROGRAM |
| int main(int argc, char **argv) |
| { |
| if (argc < 2) { |
| fprintf(stderr, "usage: %s <device>\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("%s: is%s whole disk\n", argv[1], |
| is_whole_disk(argv[1]) ? "" : " NOT"); |
| exit(EXIT_SUCCESS); |
| } |
| #endif |