diff options
Diffstat (limited to 'utils/scsi')
-rw-r--r-- | utils/scsi/rbscsi.c | 22 | ||||
-rw-r--r-- | utils/scsi/rbscsi.h | 15 |
2 files changed, 35 insertions, 2 deletions
diff --git a/utils/scsi/rbscsi.c b/utils/scsi/rbscsi.c index aa62ba0118..8a263f29e6 100644 --- a/utils/scsi/rbscsi.c +++ b/utils/scsi/rbscsi.c | |||
@@ -151,13 +151,33 @@ void rb_scsi_close(rb_scsi_device_t dev) | |||
151 | 151 | ||
152 | /* Windpws */ | 152 | /* Windpws */ |
153 | #elif defined(RB_SCSI_WINDOWS) | 153 | #elif defined(RB_SCSI_WINDOWS) |
154 | /* return either path or something allocated with malloc() */ | ||
155 | static const char *map_to_physical_drive(const char *path, unsigned flags, void *user, | ||
156 | rb_scsi_printf_t printf) | ||
157 | { | ||
158 | /* don't do anything if path starts with '\' */ | ||
159 | if(path[0] == '\\') | ||
160 | return path; | ||
161 | /* Convert to UNC path (C: -> \\.\C:) otherwise it won't work) */ | ||
162 | char *unc_path = malloc(strlen(path) + 5); | ||
163 | sprintf(unc_path, "\\\\.\\%s", path); | ||
164 | if(flags & RB_SCSI_DEBUG) | ||
165 | printf(user, "rb_scsi: map to UNC path: %s\n", unc_path); | ||
166 | return unc_path; | ||
167 | } | ||
168 | |||
154 | rb_scsi_device_t rb_scsi_open(const char *path, unsigned flags, void *user, | 169 | rb_scsi_device_t rb_scsi_open(const char *path, unsigned flags, void *user, |
155 | rb_scsi_printf_t printf) | 170 | rb_scsi_printf_t printf) |
156 | { | 171 | { |
157 | if(printf == NULL) | 172 | if(printf == NULL) |
158 | printf = misc_std_printf; | 173 | printf = misc_std_printf; |
159 | HANDLE h = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | 174 | /* magic to auto-detect physical drive */ |
175 | const char *open_path = map_to_physical_drive(path, flags, user, printf); | ||
176 | HANDLE h = CreateFileA(open_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
160 | NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); | 177 | NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); |
178 | /* free path if it was allocated */ | ||
179 | if(open_path != path) | ||
180 | free((char *)open_path); | ||
161 | if(h == INVALID_HANDLE_VALUE) | 181 | if(h == INVALID_HANDLE_VALUE) |
162 | { | 182 | { |
163 | if(flags & RB_SCSI_DEBUG) | 183 | if(flags & RB_SCSI_DEBUG) |
diff --git a/utils/scsi/rbscsi.h b/utils/scsi/rbscsi.h index 2b56aabad2..c7345a6cdf 100644 --- a/utils/scsi/rbscsi.h +++ b/utils/scsi/rbscsi.h | |||
@@ -66,7 +66,20 @@ struct rb_scsi_raw_cmd_t | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* open a device, returns a handle or NULL on error | 68 | /* open a device, returns a handle or NULL on error |
69 | * the caller can optionally provide an error printing function */ | 69 | * the caller can optionally provide an error printing function |
70 | * | ||
71 | * Linux: | ||
72 | * Path must be the block device, typically /dev/sdX and the program | ||
73 | * must have the permission to open it in read/write mode. | ||
74 | * | ||
75 | * Windows: | ||
76 | * If the path starts with '\', it will be use as-is. This allows to use | ||
77 | * paths such as \\.\PhysicalDriveX or \\.\ScsiX | ||
78 | * Alternatively, the code will try to map a logical drive (such as 'C:') to | ||
79 | * the correspoding physical drive. | ||
80 | * In any case, on recent windows, the program needs to be started with | ||
81 | * Administrator privileges. | ||
82 | */ | ||
70 | rb_scsi_device_t rb_scsi_open(const char *path, unsigned flags, void *user, | 83 | rb_scsi_device_t rb_scsi_open(const char *path, unsigned flags, void *user, |
71 | rb_scsi_printf_t printf); | 84 | rb_scsi_printf_t printf); |
72 | /* performs a raw transfer, returns !=0 on error */ | 85 | /* performs a raw transfer, returns !=0 on error */ |