1
/* Copyright (c) 1996-2004, Adaptec Corporation
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* - Redistributions of source code must retain the above copyright notice, this
8
* list of conditions and the following disclaimer.
9
* - Redistributions in binary form must reproduce the above copyright notice,
10
* this list of conditions and the following disclaimer in the documentation
11
* and/or other materials provided with the distribution.
12
* - Neither the name of the Adaptec Corporation nor the names of its
13
* contributors may be used to endorse or promote products derived from this
14
* software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
* POSSIBILITY OF SUCH DAMAGE.
30
* UNIX based drive busy checking routine.
32
* 1999/02/11 salyzyn@dpt.com
37
#include "drv_busy.hpp"
41
#if (defined(_DPT_WIN_NT))
42
int DPTDriveBusy::drvBusy(int hba, int bus, int target, int lun)
47
int DPTDriveBusy::newDeviceList (DPTDeviceList ** List, char * name)
50
char * Head = Buffer = Strdup(name);
52
DPTDeviceList * Link = *List;
53
DPTDeviceList * New = (DPTDeviceList *)NULL;
57
/* Parse out major, minor and links */
58
static char ls[] = "ls -ld %s 2>/dev/null | sed -n '"
59
"s#.* \\([0-9][0-9]*\\),[ ]*\\([0-9][0-9]*\\).*#\\1 \\2#p\n"
61
"s#^l.* \\([^ ]*/\\)[^/ ]*/[^/ ]*/[^/ ]*/[^/ ]* -> \\.\\./\\.\\./\\.\\./\\([^ ][^ ]*\\)$# \\1\\2#p\n"
62
"s#^l.* \\([^ ]*/\\)[^/ ]*/[^/ ]*/[^/ ]* -> \\.\\./\\.\\./\\([^ ][^ ]*\\)$#l\\1\\2#p\n"
63
"s#^l.* \\([^ ]*/\\)[^/ ]*/[^/ ]* -> \\.\\./\\([^ ][^ ]*\\)$#l\\1\\2#p\n"
64
"s#^l.* \\([^ ]*/\\)[^/ ]* -> \\([^/ ][^ ]*\\)$#l\\1\\2#p\n"
65
"s#^l.* -> \\([^ ][^ ]*\\)$#l\\1#p'";
66
static char eol[] = " \t\r\n";
69
while (((Path = strtok (Head, eol)) != NULL) && (Path[0] != '\0')) {
71
if ((Next = (DPTDeviceList *)new char[sizeof(DPTDeviceList)
72
+ strlen(Path)]) != (DPTDeviceList *)NULL) {
74
Next->Link = (DPTDeviceList *)NULL;
77
(void)strcpy (Next->Name, Path);
90
/* Find any links, or device information, and extend them */
91
if (New) /* Any new entries to check? */
92
for (Link = *List; Link != (DPTDeviceList *)NULL; Link = Link->Link) {
94
Buffer = new char[sizeof(ls) + strlen(Link->Name) - 1];
95
sprintf (Buffer, ls, Link->Name);
96
fp = SafePopenRead (Buffer);
99
Buffer = new char[512];
100
while (fgets(Buffer, 512, fp)) {
102
case 'd': /* Mark it as the mount point */
106
case 'l': /* It's a link to a device */
107
if ((Next = (DPTDeviceList *)new char[sizeof(DPTDeviceList)
108
+ strlen(Buffer + 1)]) != (DPTDeviceList *)NULL) {
109
Next->Next = Link->Next;
110
Next->Link = Link->Link;
113
(void)strcpy (Next->Name, strtok (Buffer + 1, eol));
119
default: /* It's the mount device */
120
if ((Path = strtok(Buffer, eol)) != (char *)NULL) {
121
Link->Major = atoi(Path);
122
if ((Path = strtok ((char *)NULL, eol)) != (char *)NULL) {
123
Link->Minor = atoi(Path);
135
void DPTDriveBusy::deleteDeviceList (DPTDeviceList * List)
137
if (List != (DPTDeviceList *)NULL) {
138
DPTDeviceList * Link;
140
if ((Link = List->Link) == (DPTDeviceList *)NULL) {
143
delete [] ((char *) List);
144
} while ((List = Link) != (DPTDeviceList *)NULL);
148
static char *TargetStringDirs[] = {
156
static char *TargetStringSuffixes[] = {
158
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
159
"a", "b", "c", "d", "e", "f", "g", "h",
163
static char *TargetPathDirs[] = {
169
static char *TargetPathSuffixes[] = {
171
":a", ":b", ":c", ":d", ":e", ":f", ":g", ":h",
175
int DPTDriveBusy::drvBusy(int hba, int bus, int target, int lun)
177
char ** Dirs[sizeof(Targets)/sizeof(Targets[0])];
178
char ** Suffixes[sizeof(Targets)/sizeof(Targets[0])];
180
DPTDeviceList * Mounts = (DPTDeviceList *)NULL;
183
/* Initialize the local structures */
184
Targets[0] = getTargetString(hba, bus, target, lun);
185
Dirs[0] = TargetStringDirs;
186
Suffixes[0] = TargetStringSuffixes;
187
Targets[1] = getTargetPath(hba, bus, target, lun);
188
Dirs[1] = TargetPathDirs;
189
Suffixes[1] = TargetPathSuffixes;
191
for (SuffixIndex = 0;;) {
192
while (Targets[0] == (char *)NULL) {
193
int Index, NoneZero = 0;
195
for (Index = sizeof(Targets)/sizeof(Targets[0]); Index; --Index) {
196
if ((Targets[Index-2] = Targets[Index-1]) != (char *)NULL) {
199
Targets[Index-1] = (char *)NULL;
200
Dirs[Index-2] = Dirs[Index-1];
201
Suffixes[Index-2] = Suffixes[Index-1];
207
if (Targets[0] == (char *)NULL) {
211
/* Check if the Dirs/Targets entry exists */
212
{ char * name = new char[strlen(Dirs[0][0]) + strlen(Targets[0])
213
+ strlen(Suffixes[0][SuffixIndex]) + 1];
215
if (name == (char *)NULL) {
219
(void)strcat(strcat(strcpy(name,
220
Dirs[0][0]), Targets[0]), Suffixes[0][SuffixIndex]);
221
switch(PathExists(name)) {
222
case PathExists_Exists:
223
case PathExists_Read:
224
case PathExists_Open:
225
/* Check if the Dirs/Target entry is mounted */
226
if (Mounts == (DPTDeviceList *)NULL) {
227
FILE * fp = SafePopenRead("mount | sed -n '"
228
"s/^\\([^ ][^ ]*\\)[ ][ ]*on[ ][ ]*\\([^ ][^ ]*\\).*/\\1 \\2/p'");
229
char * Buffer = new char[512];
231
while (fgets (Buffer, 512, fp)) {
232
if (newDeviceList (&Mounts, Buffer)) {
240
# if (defined(DEBUG) && (DEBUG > 0))
241
if (Mounts != (DPTDeviceList *)NULL) {
242
DPTDeviceList * List = Mounts;
243
DPTDeviceList * Link;
245
printf ("Mount list:\n");
247
printf ("%s", List->Name);
248
if ((List->Major == -2)
249
&& (List->Minor == -2)) {
251
} else if ((List->Major != -1)
252
|| (List->Minor != -1)) {
254
List->Major, List->Minor);
256
if ((Link = List->Link)
257
== (DPTDeviceList *)NULL) {
263
} while ((List = Link) != (DPTDeviceList *)NULL);
267
/* We have an initialized mount database, search! */
269
DPTDeviceList * Link;
270
DPTDeviceList * Names = (DPTDeviceList *)NULL;
272
newDeviceList (&Names, name);
273
for (Link = Mounts; Link != (DPTDeviceList *)NULL; ) {
274
DPTDeviceList * Next;
277
(Name = Name->Link) != (DPTDeviceList *)NULL; ) {
278
/* Same name, or same device */
279
if ((strcmp (Name->Name, Link->Name) == 0)
280
|| ((Name->Major == Link->Major)
281
&& (Name->Minor == Link->Minor))) {
285
if (Name != (DPTDeviceList *)NULL) {
289
if ((Next = Link->Link) == (DPTDeviceList *)NULL) {
294
deleteDeviceList (Names);
298
case PathExists_Busy:
299
RetVal = 1; /* It's busy even before we hit the ground */
300
case PathExists_None:
306
if ((RetVal != -1) && (RetVal != 0)) {
310
if (Suffixes[0][++SuffixIndex] == (char *)NULL) {
312
if ((++(Dirs[0]))[0] == (char *)NULL) {
313
delete [] Targets[0];
314
Targets[0] = (char *)NULL;
318
/* Free up resources */
321
for (Index = 0; Index < (sizeof(Targets)/sizeof(Targets[0])); ++Index) {
322
if (Targets[Index] != (char *)NULL) {
323
delete [] Targets[Index];
327
deleteDeviceList (Mounts);
333
/* `C' interface routine */
335
int drv_busy(int hba, int bus, int target, int lun)
338
DPTControllerMap::Reset();
341
DPTDriveBusy * obj = new DPTDriveBusy();
342
int retVal = obj->drvBusy(hba, bus, target, lun);
348
main (int argc, char ** argv)
350
int hba, bus, target, lun;
352
hba = bus = target = lun = 0;
361
target = atoi(argv[3]);
366
printf ("d%db%dt%dd%d: ", hba, bus, target, lun);
367
switch (drv_busy (hba, bus, target, lun)) {
369
printf ("not busy\n");
375
printf ("not found\n");
378
printf ("allocation error\n");
391
# include "ctlr_map.cpp"