source: trunk/third/sysinfo/os-sunos5.c @ 12269

Revision 12269, 38.7 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12268, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1992-1998 Michael A. Cooper.
3 * This software may be freely used and distributed provided it is not
4 * sold for profit or used in part or in whole for commercial gain
5 * without prior written agreement, and the author is credited
6 * appropriately.
7 */
8
9#ifndef lint
10static char *RCSid = "$Revision: 1.1.1.3 $";
11#endif
12
13/*
14 * SunOS 5.x specific routines
15 */
16
17#include "defs.h"
18#include <dirent.h>
19#include <sys/stat.h>
20#include <sys/cdio.h>
21#include <sys/fdio.h>
22#if     defined(HAVE_VOLMGT)
23#include <volmgt.h>
24#endif  /* HAVE_VOLMGT */
25
26/*
27 * CPU (model) symbol
28 */
29char                            CpuSYM[] = "_cputype";
30
31static char                     Buff[BUFSIZ];
32DevInfo_t                      *DevInfo;
33extern char                     RomVecSYM[];
34struct stat                     StatBuf;
35
36/*
37 * Get device file list.
38 * Finds a list of match device files.
39 * File list is set to ArgvPtr.
40 * Returns number of files found (in ArgvPtr).
41 *
42 * If DevDefine->File is set, use that to find file name.
43 * Otherwise, scan DevDir looking for a device file that matches
44 * DevData->DevNum.
45 */
46static int GetDeviceFile(ProbeData, DevDir, ArgvPtr)
47     ProbeData_t               *ProbeData;
48     char                      *DevDir;
49     char                    ***ArgvPtr;
50{
51    static DIR                 *DirPtr = NULL;
52    struct dirent              *DirEnt;
53    static char                 PathBuff[MAXPATHLEN];
54    char                       *Path = PathBuff;
55    static char                 LastDir[MAXPATHLEN];
56    register int                i;
57    int                         Len;
58    int                         Argc;
59    char                      **Argv = NULL;
60    static char               **FileArgv = NULL;
61    static int                  FileArgc = 0;
62    char                       *File;
63    DevData_t                  *DevData;
64    DevDefine_t                *DevDefine;
65
66    if (!ProbeData)
67        return(0);
68    DevData = ProbeData->DevData;
69    DevDefine = ProbeData->DevDefine;
70
71    /* Don't bother trying if the devnum is 0 */
72    if (DevData->DevNum <= 0)
73        return(0);
74
75    if (FileArgv && FileArgc > 0) {
76        DestroyArgv(&FileArgv, FileArgc);
77        FileArgv = NULL;
78        FileArgc = 0;
79    }
80
81    if (DevDefine->File) {
82        /*
83         * DevDefine->File is a space seperated list of file names.
84         * If a '%' is found, then the unit number is inserted at
85         * that point.
86         */
87        Argc = StrToArgv(DevDefine->File, " ", &Argv, NULL, 0);
88        if (Argc <= 0)
89            return(0);
90        FileArgv = (char **) xcalloc(Argc, sizeof(char **));
91        for (i = 0; i < Argc; ++i) {
92            File = Argv[i];
93            /* Allow NULL members of Argv */
94            if (!File || !File[0])
95                continue;
96            /*
97             * If File doesn't start with '/', then insert DevDir.
98             * If File contains '%', then insert the device number.
99             */
100            PathBuff[0] = CNULL;
101            if (File[0] != '/')
102                (void) snprintf(PathBuff, sizeof(PathBuff),  "%s/", DevDir);
103            Path = PathBuff + (Len = strlen(PathBuff));
104
105            if (strchr(File, '%') && DevData->DevUnit >= 0)
106                (void) snprintf(Path, sizeof(PathBuff)-Len,
107                                File, DevData->DevUnit);
108            else
109                (void) strcat(Path, File);
110
111            if (Path[0]) {
112                if (stat(Path, &StatBuf) == 0)
113                    FileArgv[FileArgc++] = strdup(Path);
114                else {
115                    SImsg(SIM_GERR, "Stat of %s failed: %s.", Path, SYSERR);
116                    Argv[i] = NULL;
117                }
118            } else
119                SImsg(SIM_DBG, "Convert pathname failed: %s", File);
120        }
121        if (Argc)
122            DestroyArgv(&Argv, Argc);
123    } else {
124        if (!DirPtr || !EQ(DevDir, LastDir)) {
125            if (!(DirPtr = opendir(DevDir))) {
126                SImsg(SIM_GERR, "Cannot open directory \"%s\": %s",
127                      DevDir, SYSERR);
128                return(-1);
129            }
130            (void) strcpy(LastDir, DevDir);
131        } else
132            rewinddir(DirPtr);
133
134        Path = PathBuff;
135        while (DirEnt = readdir(DirPtr)) {
136            if (EQ(DirEnt->d_name, ".") || EQ(DirEnt->d_name, ".."))
137                continue;
138       
139            (void) snprintf(Path, sizeof(PathBuff), "%s/%s",
140                            DevDir, DirEnt->d_name);
141
142            if (stat(Path, &StatBuf) < 0) {
143                SImsg(SIM_GERR, "Stat of %s failed: %s.", Path, SYSERR);
144                continue;
145            }
146
147#if     defined(DEBUG_VERBOSE)
148            SImsg(SIM_DBG, "GetDeviceFile dev '%s' (%d) got '%s' (%d)",
149                  DevData->DevName, DevData->DevNum,
150                  Path, StatBuf.st_rdev);
151#endif  /* DEBUG_VERBOSE */
152
153            if (StatBuf.st_rdev == DevData->DevNum) {
154                FileArgv = (char **) xcalloc(2, sizeof(char *));
155                FileArgv[FileArgc++] = strdup(Path);
156                break;
157            }
158        }
159    }
160
161    if (FileArgc)
162        *ArgvPtr = FileArgv;
163
164    return(FileArgc);
165}
166
167/*
168 * Create a tape device
169 */
170static DevInfo_t *CreateTapeDrive(ProbeData, DevName, TapeName)
171     ProbeData_t               *ProbeData;
172     char                      *DevName;
173     char                      *TapeName;
174{
175    DevInfo_t                  *DevInfo;
176
177    ProbeData->DevName = DevName;
178    DevInfo = DeviceCreate(ProbeData);
179    if (!EQ(DevName, TapeName))
180        DevInfo->AltName = strdup(TapeName);
181    DevInfo->Type               = DT_TAPEDRIVE;
182
183    return(DevInfo);
184}
185
186/*
187 * Probe a Tape Drive.
188 */
189extern DevInfo_t *ProbeTapeDrive(ProbeData)
190     ProbeData_t               *ProbeData;
191{
192    DevInfo_t                  *DevInfo;
193    char                       *DevFile;
194    char                       *DevName;
195    char                       *Model = NULL;
196    char                      **FileList;
197    int                         FileNum;
198    static char                 DevFilen[MAXPATHLEN];
199    struct mtget                mtget;
200    register char              *cp;
201    int                         fd;
202    DevDesc_t                  *ScsiDevDesc;
203    char                       *TapeName;
204    DevData_t                  *DevData;
205    DevDefine_t                *DevDefine;
206
207    TapeName = ProbeData->DevName;
208    DevData = ProbeData->DevData;
209    DevDefine = ProbeData->DevDefine;
210
211    FileNum = GetDeviceFile(ProbeData, _PATH_DEV_RMT, &FileList);
212    if (FileNum < 1) {
213        SImsg(SIM_GERR, "Cannot find tape device for <%s>", TapeName);
214        return((DevInfo_t *)NULL);
215    }
216    /* Only bother with the first file name */
217    DevFile = FileList[0];
218
219    /*
220     * Use DevFile to get name of device.
221     * Takes something like "/dev/rmt/0l" and
222     * turns it into "rmt/0".
223     */
224    cp = DevFile;
225    /* Skip over "/dev/" */
226    if ((int)strlen(DevFile) > 5 && EQN(DevFile, "/dev/", 4))
227        cp += 5;
228    DevName = cp;
229    if (cp = strrchr(DevFile, '/')) {
230        ++cp;
231        while (isdigit(*++cp));
232        if (*cp && !isdigit(*cp))
233            *cp = CNULL;
234    }
235
236    /* Use the no rewind file */
237    (void) snprintf(DevFilen, sizeof(DevFilen), "%sn", DevFile);
238
239    /*
240     * The O_NDELAY flag will allow the device to be opened even if no
241     * media is loaded.
242     */
243    if ((fd = open(DevFilen, O_RDONLY|O_NDELAY)) < 0) {
244        SImsg(SIM_GERR, "%s Cannot open for read: %s.", DevFilen, SYSERR);
245
246        /*
247         * If we know for sure this drive is present and we
248         * know something about it, then create a minimal device.
249         */
250        if ((DevDefine->Model || DevDefine->Desc) &&
251            FLAGS_ON(DevData->Flags, DD_IS_ALIVE)) {
252            DevInfo = CreateTapeDrive(ProbeData, DevName, TapeName);
253            return(ProbeData->RetDevInfo = DevInfo);
254        } else
255            return((DevInfo_t *) NULL);
256    }
257
258    if (ioctl(fd, MTIOCGET, &mtget) != 0) {
259        SImsg(SIM_GERR, "%s: Cannot extract tape status: %s.",
260              DevName, SYSERR);
261        return((DevInfo_t *) NULL);
262    }
263
264    cp = GetTapeModel(mtget.mt_type);
265    if (cp)
266        Model = strdup(cp);
267    else
268        Model = "unknown";
269
270    /*
271     * Set device info
272     */
273    DevInfo = CreateTapeDrive(ProbeData, DevName, TapeName);
274    if (Model)
275        DevInfo->Model          = Model;
276    else
277        DevInfo->Model          = DevDefine->Model;
278    DevInfo->Master             = MkMasterFromDevData(DevData);
279
280    (void) ScsiQuery(DevInfo, DevFilen, fd, TRUE);
281
282    (void) close(fd);
283
284    return(ProbeData->RetDevInfo = DevInfo);
285}
286
287/*
288 * Get SVR4 style partition information
289 */
290DKvtoc *GETvtoc(fd, DevFile)
291    int                         fd;
292    char                       *DevFile;
293{
294    static DKvtoc               vtoc;
295
296    if (ioctl(fd, DKIOCGVTOC, &vtoc) < 0) {
297        SImsg(SIM_GERR, "%s: DKIOCGVTOC failed: %s.", DevFile, SYSERR);
298        return((DKvtoc *)NULL);
299    }
300
301    return(&vtoc);
302}
303
304/*
305 * Get controller information
306 */
307DKcinfo *GETdk_cinfo(fd, DevFile)
308    int                         fd;
309    char                       *DevFile;
310{
311    static DKcinfo              dk_cinfo;
312
313    if (ioctl(fd, DKIOCINFO, &dk_cinfo) < 0) {
314        SImsg(SIM_GERR, "%s: DKIOCINFO failed: %s.", DevFile, SYSERR);
315        return((DKcinfo *)NULL);
316    }
317
318    return(&dk_cinfo);
319}
320
321/*
322 * Get disk geometry
323 */
324DKgeom *GETdk_geom(fd, DevFile)
325    int                         fd;
326    char                       *DevFile;
327{
328    static DKgeom               dk_geom;
329
330    if (ioctl(fd, DKIOCGGEOM, &dk_geom) < 0) {
331        SImsg(SIM_GERR, "%s: DKIOCGGEOM failed: %s.", DevFile, SYSERR);
332        return((DKgeom *)NULL);
333    }
334
335    return(&dk_geom);
336}
337
338#if     defined(HAVE_HDIO)
339/*
340 * Get disk type structure.
341 */
342static DKtype *GETdk_type(fd, file)
343    int                         fd;
344    char                       *file;
345{
346    static DKtype               dk_type;
347
348    if (ioctl(fd, HDKIOCGTYPE, &dk_type) < 0) {
349        if (errno != ENOTTY)
350            SImsg(SIM_GERR, "%s: DKIOCGTYPE failed: %s.", file, SYSERR);
351        return(NULL);
352    }
353
354    return(&dk_type);
355}
356#endif  /* HAVE_HDIO */
357
358/*
359 * Find mount point for a given device
360 */
361static char *GetMountInfo(DevName, PartName)
362    char                       *DevName;
363    char                       *PartName;
364{
365    static FILE                *mntFilePtr = NULL;
366    static FILE                *vfstabFilePtr = NULL;
367    struct mnttab               MntTab;
368    struct vfstab               vfstab;
369    static char                 Name[MAXPATHLEN];
370    static char                 Path[MAXPATHLEN];
371    register char              *cp;
372
373    if (!DevName || !PartName)
374        return((char *) NULL);
375
376    (void) snprintf(Name, sizeof(Name),  "%s%s", DevName, PartName);
377
378    /*
379     * First try the current mount table
380     */
381    if (!mntFilePtr) {
382        if ((mntFilePtr = fopen(MNTTAB, "r")) == NULL) {
383            SImsg(SIM_GERR, "%s: Cannot open for reading: %s.",
384                  MNTTAB, SYSERR);
385            return(NULL);
386        }
387    } else
388        rewind(mntFilePtr);
389
390    while (getmntent(mntFilePtr, &MntTab) == 0) {
391        if (!MntTab.mnt_special)
392            continue;
393        if (cp = strrchr(MntTab.mnt_special, '/'))
394            ++cp;
395        else
396            cp = MntTab.mnt_special;
397        if (EQ(cp, Name))
398            return(strdup(MntTab.mnt_mountp));
399    }
400
401    /*
402     * Now try the static mount table, which may not reflect current reality.
403     */
404    if (!vfstabFilePtr) {
405        if ((vfstabFilePtr = fopen(VFSTAB, "r")) == NULL) {
406            SImsg(SIM_GERR, "%s: Cannot open for reading: %s.",
407                  VFSTAB, SYSERR);
408            return(NULL);
409        }
410    } else
411        rewind(vfstabFilePtr);
412
413    (void) snprintf(Path, sizeof(Path), "%s/%s", _PATH_DEV_DSK, Name);
414
415    if (getvfsspec(vfstabFilePtr, &vfstab, Path) == 0) {
416        if (EQ(vfstab.vfs_fstype, "swap"))
417            return("swap");
418        else if (vfstab.vfs_mountp && !EQ(vfstab.vfs_mountp, "-"))
419            return(strdup(vfstab.vfs_mountp));
420    }
421
422    return((char *) NULL);
423}
424
425/*
426 * Translate disk partition information from basic
427 * extracted disk info.
428 */
429static DiskPart_t *GetDiskPart(DevName, dk_vtoc)
430    char                       *DevName;
431    DKvtoc                     *dk_vtoc;
432{
433    register ushort             i;
434    static char                 pname[4];
435    DiskPart_t                 *Base = NULL;
436    DiskPart_t                 *Last = NULL;
437    DiskPart_t                 *DiskPart = NULL;
438
439    if (!DevName || !dk_vtoc)
440        return((DiskPart_t *) NULL);
441
442    pname[2] = CNULL;
443    /*
444     * dk_vtoc->v_nparts is always 0 after the first time through
445     * here, so we use V_NUMPAR.
446     */
447    for (i = 0; i < V_NUMPAR; ++i) {
448        /* Skip partitions that have no size */
449        if (!dk_vtoc->v_part[i].p_size)
450            continue;
451        DiskPart = (DiskPart_t *) xcalloc(1, sizeof(DiskPart_t));
452        (void) snprintf(pname, sizeof(pname),  "s%d", i);
453        DiskPart->Name = strdup(pname);
454        DiskPart->Usage = GetMountInfo(DevName, pname);
455        DiskPart->StartSect = (Large_t) dk_vtoc->v_part[i].p_start;
456        DiskPart->NumSect = (Large_t) dk_vtoc->v_part[i].p_size;
457
458        if (Base) {
459            Last->Next = DiskPart;
460            Last = DiskPart;
461        } else
462            Base = Last = DiskPart;
463    }
464
465    return(Base);
466}
467
468/*
469 * Extract disk label
470 */
471static char *GetDiskLabel(dk_vtoc)
472    DKvtoc                     *dk_vtoc;
473{
474    register char              *cp;
475    register char              *bp;
476    register char              *end;
477    char                       *Label = NULL;
478
479    if (!dk_vtoc || !dk_vtoc->v_asciilabel)
480        return((char *)NULL);
481
482    Label = dk_vtoc->v_asciilabel;
483
484    /*
485     * The label normally has geometry information in it we don't want
486     * to see, so we trim out anything starting with " cyl".
487     */
488    for (cp = Label; cp && *cp; ++cp)
489        if (*cp == ' ' && strncasecmp(cp, " cyl", 4) == 0) {
490            *cp = CNULL;
491            break;
492        }
493
494    /*
495     * Zap any trailing white space we find
496     */
497    bp = Label;
498    bp += strlen(Label);
499    end = bp;
500    for (cp = end - 1; cp > Label && *cp == ' '; --cp);
501    if (cp != end - 1 && cp && *++cp == ' ')
502        *cp = CNULL;
503
504    /*
505     * Check what we have so far.
506     * "DEFAULT" is sometimes used by Solaris x86.
507     */
508    if (!Label || !Label[0] || EQ(Label, "DEFAULT"))
509        return((char *) NULL);
510
511    return(strdup(Label));
512}
513
514/*
515 * Get the name of the controller for a disk.
516 */
517static char *GetDkCtlrName(dk_cinfo)
518    DKcinfo                    *dk_cinfo;
519{
520    if (!dk_cinfo)
521        return((char *) NULL);
522
523    (void) snprintf(Buff, sizeof(Buff), "%s%d",
524                    dk_cinfo->dki_cname, dk_cinfo->dki_cnum);
525
526    return(strdup(Buff));
527}
528
529/*
530 * Get a disk controller device from disk info.
531 */
532static DevInfo_t *GetDkCtlrDevice(DevData, dk_cinfo)
533    DevData_t                  *DevData;
534    DKcinfo                    *dk_cinfo;
535{
536    DevInfo_t                  *MkMasterFromDevData();
537    DevInfo_t                  *DiskCtlr;
538
539    if (!dk_cinfo)
540        return((DevInfo_t *) NULL);
541
542    /*
543     * Get name of controller from devdata if available
544     */
545    if (DevData && DevData->CtlrName)
546        DiskCtlr = MkMasterFromDevData(DevData);
547    else {
548        if ((DiskCtlr = NewDevInfo(NULL)) == NULL)
549            return((DevInfo_t *) NULL);
550    }
551
552    DiskCtlr->Type = DT_DISKCTLR;
553
554    /*
555     * Get name of controller from devdata if available
556     */
557    if (DevData && DevData->CtlrName)
558        DiskCtlr = MkMasterFromDevData(DevData);
559
560    if (!DiskCtlr->Name) {
561        DiskCtlr->Name = GetDkCtlrName(dk_cinfo);
562        DiskCtlr->Unit = dk_cinfo->dki_cnum;
563    }
564    DiskCtlr->Addr = dk_cinfo->dki_addr;
565    DiskCtlr->Prio = dk_cinfo->dki_prio;
566    DiskCtlr->Vec = dk_cinfo->dki_vec;
567    SetDiskCtlrModel(DiskCtlr, dk_cinfo->dki_ctype);
568
569    return(DiskCtlr);
570}
571
572/*
573 * Convert all we've learned about a disk to a DevInfo_t.
574 */
575static DevInfo_t *CreateDiskDrive(ProbeData, DevName,
576                                  dk_vtoc, dk_cinfo, dk_geom, dk_type)
577     ProbeData_t               *ProbeData;
578     char                      *DevName;
579     DKvtoc                    *dk_vtoc;
580     DKcinfo                   *dk_cinfo;
581     DKgeom                    *dk_geom;
582     DKtype                    *dk_type;
583{
584    DevInfo_t                  *DevInfo;
585    DevInfo_t                  *DiskCtlr = NULL;
586    DiskDriveData_t            *DiskDriveData = NULL;
587    DiskDrive_t                *DiskDrive = NULL;
588    DevData_t                  *DevData;
589    static DevInfo_t            ScsiDevInfo;
590    int                         GotScsi = FALSE;
591    int                         DevFD;
592
593    if (!ProbeData)
594        return((DevInfo_t *) NULL);
595
596    DevFD = ProbeData->FileDesc;
597    DevData = ProbeData->DevData;
598
599    ProbeData->DevName = DevName;
600    if (!(DevInfo = DeviceCreate(ProbeData))) {
601        SImsg(SIM_GERR, "Cannot create new device entry.");
602        return((DevInfo_t *) NULL);
603    }
604
605    /*
606     * We call ScsiQuery() here because it needs a DevInfo to operate on.
607     */
608    if (ScsiQuery(DevInfo, ProbeData->DevFile, DevFD, TRUE) == 0)
609        GotScsi = TRUE;
610
611    if (dk_vtoc == NULL) {
612        SImsg(SIM_GERR, "%s: No table of contents found on disk.", DevName);
613        if (!GotScsi)
614            return((DevInfo_t *) NULL);
615    }
616
617    if (DevInfo->DevSpec)
618        DiskDriveData = (DiskDriveData_t *) DevInfo->DevSpec;
619    else {
620        if ((DiskDriveData = NewDiskDriveData(NULL)) == NULL) {
621            SImsg(SIM_GERR, "Cannot create new DiskDriveData entry.");
622            return((DevInfo_t *) NULL);
623        }
624        DevInfo->DevSpec = (void *) DiskDriveData;
625    }
626
627    if ((DiskDrive = NewDiskDrive(NULL)) == NULL) {
628        SImsg(SIM_GERR, "Cannot create new DiskDrive entry.");
629        return((DevInfo_t *) NULL);
630    }
631    /*
632     * DiskDrive is the OS DiskDrive data
633     */
634    DiskDriveData->OSdata = DiskDrive;
635
636    (void) snprintf(Buff, sizeof(Buff), "%s%d",
637                    DevData->DevName, DevData->DevUnit);
638    DevInfo->AltName            = strdup(Buff);
639    DevInfo->Type               = DT_DISKDRIVE;
640
641    if (dk_vtoc && dk_vtoc->v_sanity == VTOC_SANE) {
642        /*
643         * Only read partition info we we're going to print it later.
644         */
645        if (VL_ALL)
646            DiskDrive->DiskPart = GetDiskPart(DevName, dk_vtoc);
647        if (!DiskDrive->Label)
648            DiskDrive->Label    = GetDiskLabel(dk_vtoc);
649        DiskDrive->SecSize      = dk_vtoc->v_sectorsz;
650        if (dk_vtoc->v_volume[0]) {
651            (void) snprintf(Buff, sizeof(Buff), "\"%.*s\"",
652                            sizeof(dk_vtoc->v_volume), dk_vtoc->v_volume);
653            AddDevDesc(DevInfo, Buff, "Volume Name", DA_APPEND);
654        }
655    }
656    if (!DevInfo->Model)
657        DevInfo->Model          = DiskDrive->Label;
658
659    if (dk_cinfo) {
660        DiskDrive->Unit         = dk_cinfo->dki_unit;
661        DiskDrive->Slave        = dk_cinfo->dki_slave;;
662    }
663    if (dk_geom) {
664        DiskDrive->DataCyl      = dk_geom->dkg_ncyl;
665        DiskDrive->PhyCyl       = dk_geom->dkg_pcyl;
666        DiskDrive->AltCyl       = dk_geom->dkg_acyl;
667        DiskDrive->Tracks       = dk_geom->dkg_nhead;
668        DiskDrive->Sect         = dk_geom->dkg_nsect;
669        DiskDrive->APC          = dk_geom->dkg_apc;
670        DiskDrive->RPM          = dk_geom->dkg_rpm;
671        DiskDrive->IntrLv       = dk_geom->dkg_intrlv;
672    }
673#if     defined(HAVE_HDIO)
674    if (dk_type) {
675        DiskDrive->PhySect      = dk_type->hdkt_hsect;
676        DiskDrive->PROMRev      = dk_type->hdkt_promrev;
677    }
678#endif  /* HAVE_HDIO */
679
680    if (DiskCtlr = GetDkCtlrDevice(DevData, dk_cinfo))
681      DevInfo->Master           = DiskCtlr;
682
683#if     defined(i386)
684    (void) DosPartGet(DevInfo);
685#endif
686
687    return(ProbeData->RetDevInfo = DevInfo);
688}
689
690/*
691 * Create a base DiskDrive device.
692 */
693static DevInfo_t *CreateBaseDiskDrive(ProbeData, DiskName)
694     ProbeData_t               *ProbeData;
695     char                      *DiskName;
696{
697    DevInfo_t                  *DevInfo;
698    DevData_t                  *DevData;
699    DevDefine_t                *DevDefine;
700    char                       *DevName;
701    char                       *AltName = NULL;
702
703    DevName = ProbeData->DevName;
704    DevData = ProbeData->DevData;
705    DevDefine = ProbeData->DevDefine;
706
707    if (DiskName)
708        ProbeData->DevName = DiskName;
709
710    DevInfo = DeviceCreate(ProbeData);
711    if (!DevInfo)
712        return((DevInfo_t *) NULL);
713
714    /*
715     * See if there's a good alternative name we can set.
716     */
717    if (DevData)
718        AltName = MkDevName(DevData->DevName, DevData->DevUnit,
719                            DevDefine->Type, DevDefine->Flags);
720    else if (!EQ(DiskName, DevName))
721        AltName = DiskName;
722    if (AltName && !EQ(DevInfo->Name, AltName))
723        DevInfo->AltName = strdup(AltName);
724
725    return(ProbeData->RetDevInfo = DevInfo);
726}
727
728/*
729 * Create CDROM device
730 */
731static DevInfo_t *CreateCDROM(ProbeData, DevName, CDspeed)
732     ProbeData_t               *ProbeData;
733     char                      *DevName;
734     int                        CDspeed;
735{
736    DevInfo_t                  *DevInfo;
737    Define_t                   *Def;
738
739    DevInfo = CreateBaseDiskDrive(ProbeData, DevName);
740
741    Def = DefGet(DL_CDSPEED, NULL, CDspeed, 0);
742    if (Def)
743        DevInfo->ModelDesc = Def->ValStr1;
744    else
745        SImsg(SIM_UNKN, "Unknown CDROM Speed: 0x%x", CDspeed);
746
747    return(DevInfo);
748}
749
750#if     defined(HAVE_VOLMGT)
751/*
752 * Use the Solaris Volume Management API to acquire the device.
753 * NOTE: Most of this code doesn't do us much good right now because
754 * not all ioctl()'s are passed through volfs(7) to the underlying driver.
755 * In particuliar CDROMGDRVSPEED doesn't work as of at least SunOS 5.6.
756 *
757 * Returns the pathname to the acquire device on success.
758 * Returns NULL on failure.
759 */
760static char *VolMgtAcquire(ProbeData)
761     ProbeData_t               *ProbeData;
762{
763    const char                 *VolRoot = NULL;
764    char                       *VolPath = NULL;
765    char                       *ErrPtr = NULL;
766    pid_t                       ProcID = 0;
767    char                       *cp;
768
769    if (!(VolRoot = volmgt_root())) {
770        SImsg(SIM_GERR, "Get volume manager root failed: %s", SYSERR);
771        return((char *) NULL);
772    }
773
774    VolPath = (char *) xmalloc(strlen(VolRoot) +
775                               strlen(ProbeData->DevFile) + 1);
776
777    (void) snprintf(VolPath, sizeof(VolPath),  "%s%s",
778                    VolRoot, ProbeData->DevFile);
779    /*
780     * VolPath should be something like "/vol/dev/rdsk/c0t2d0s2" for a CD.
781     * If so, remove the 'sX' from VolPath.
782     */
783    if (EQN(VolPath + strlen(VolRoot), "/dev/rdsk/c", 11))
784        if (cp = strrchr(VolPath, 's'))
785            *cp = CNULL;
786
787    if (!volmgt_acquire(VolPath, ProgramName, 0, &ErrPtr, &ProcID)) {
788        SImsg(SIM_GERR, "%s: volmgt_acquire failed: %s", VolPath, SYSERR);
789        return((char *) NULL);
790    }
791
792    return(VolPath);
793}
794
795/*
796 * Release device VolPath by calling the volmgt_* API.
797 */
798static char *VolMgtRelease(VolPath)
799     char                      *VolPath;
800{
801    if (!volmgt_release(VolPath))
802        SImsg(SIM_GERR, "%s: volmgt_release failed: %s", VolPath, SYSERR);
803
804    (void) free(VolPath);
805}
806
807/*
808 * Use VolMgt API to get attributes for a device.
809 * This only works if media is loaded.
810 */
811static void VolMgtGetAttr(ProbeData)
812     ProbeData_t               *ProbeData;
813{
814    DevInfo_t                  *DevInfo = NULL;
815    char                       *VolPath;
816    char                       *cp;
817
818    if (!ProbeData)
819        return;
820
821    DevInfo = ProbeData->UseDevInfo;
822    VolPath = ProbeData->DevFile;
823
824    if (cp = media_getattr(VolPath, "s-access")) {
825        if (EQ(cp, "seq"))
826            cp = "Sequential Access";
827        else if (EQ(cp, "rand"))
828            cp = "Random Access";
829        AddDevDesc(DevInfo, cp, "Access Type", DA_APPEND);
830    }
831
832    if (cp = media_getattr(VolPath, "s-density"))
833        AddDevDesc(DevInfo, cp, "Media Density", DA_APPEND);
834
835    if (cp = media_getattr(VolPath, "s-parts"))
836        AddDevDesc(DevInfo, cp, "Partitions", DA_APPEND);
837
838    if (cp = media_getattr(VolPath, "s-location"))
839        AddDevDesc(DevInfo, cp, "Location", DA_APPEND);
840
841    if (cp = media_getattr(VolPath, "s-mejectable"))
842        AddDevDesc(DevInfo, cp, "Has Manual Eject", DA_APPEND);
843}
844#endif  /* HAVE_VOLMGT */
845
846/*
847 * Probe a specific disk drive as file DevFile.
848 * The UsingVolMgt flag indicates whether we're using VolMgt on this call.
849 */
850static DevInfo_t *ProbeDiskDriveFile(ProbeData, UsingVolMgt)
851     ProbeData_t               *ProbeData;
852     int                        UsingVolMgt;
853{
854    DevInfo_t                  *DevInfo = NULL;
855    DKcinfo                    *dk_cinfo;
856    DKgeom                     *dk_geom;
857    DKtype                     *dk_type;
858    DKvtoc                     *dk_vtoc;
859    char                       *DevName;
860    char                       *cp;
861    int                         CDspeed = 0;
862    int                         Len;
863    int                         fd;
864    int                         Status;
865    char                       *DiskName;
866    char                       *VolDevFile = NULL;
867    char                       *DevFile;
868    DevData_t                  *DevData;
869    DevDefine_t                *DevDefine;
870
871    if (!ProbeData || !(DevFile = ProbeData->DevFile)) {
872        SImsg(SIM_GERR, "ProbeDiskDriveFile: Missing parameters.");
873        return((DevInfo_t *)NULL);
874    }
875    DiskName = ProbeData->DevName;
876    DevData = ProbeData->DevData;
877    DevDefine = ProbeData->DevDefine;
878
879    /* Use basename of DevInfo file for virtual disk device name */
880    DevName = strdup(DevFile);
881    if (cp = strrchr(DevName, '/'))
882        DevName = ++cp;
883    if (EQN(DevFile, "/dev/rdsk/c", 11)) {
884        /* Zap slice part of name */
885        if (cp = strrchr(DevName, 's'))
886            *cp = CNULL;
887    }
888
889    /*
890     * Set ProbeData for other function calls
891     */
892    ProbeData->DevFile = DevFile;
893    ProbeData->DevName = DevName;
894
895    /*
896     * Try opening the disk device.  Usually this will be the "s0" device.
897     * If that fails, try opening "s2".  Sometimes there's no "s0"
898     * partition, but there is an "s2".
899     *
900     * The O_NDELAY flag will allow the device to be opened even if no
901     * media is loaded.
902     */
903    fd = open(DevFile, O_RDONLY|O_NDELAY);
904    ProbeData->FileDesc = fd;
905    if (fd < 0) {
906        Len = strlen(DevFile);
907        if (DevFile[Len-1] == '0') {
908            DevFile[Len-1] = '2';
909            fd = open(DevFile, O_RDONLY|O_NDELAY);
910        }
911    }
912    if (fd < 0) {
913        SImsg(SIM_GERR, "%s: Cannot open for reading: %s.", DevFile, SYSERR);
914#if     defined(HAVE_VOLMGT)
915        if (errno == EBUSY && !UsingVolMgt) {
916            /*
917             * The device is busy, so let's try acquiring the device from
918             * the Volume Manager.  If that succeeds, call this function
919             * again, but use the Vol Manager device pathname.
920             */
921            if (VolDevFile = VolMgtAcquire(ProbeData)) {
922                ProbeData->DevFile = VolDevFile;
923                DevInfo = ProbeDiskDriveFile(ProbeData, TRUE);
924                ProbeData->UseDevInfo = DevInfo;
925                VolMgtGetAttr(ProbeData);
926                VolMgtRelease(VolDevFile);
927                return(DevInfo);
928            }
929        }
930#endif  /* HAVE_VOLMGT */
931        if (errno == EBUSY ||
932            ((DevDefine->Model || DevDefine->Desc || DevData->DevNum > 0) &&
933             FLAGS_ON(DevData->Flags, DD_IS_ALIVE))) {
934            /*
935             * If we know for sure this drive is present and we
936             * know something about it, then create a minimal device.
937             */
938            return(CreateBaseDiskDrive(ProbeData, DiskName));
939        }
940        return((DevInfo_t *) NULL);
941    }
942
943    Status = -1;
944#if     defined(CDROMGDRVSPEED)
945    /*
946     * If this is a DT_DISKDRIVE, it could really be a CDROM, so this is how
947     * we tell the difference.
948     */
949    if (DevDefine->Type == DT_DISKDRIVE || DevDefine->Type == DT_CDROM) {
950        Status = ioctl(fd, CDROMGDRVSPEED, &CDspeed);
951        if (Status != 0)
952            SImsg(SIM_GERR, "%s: ioctl CDROMGDRVSPEED failed: %s",
953                  DevFile, SYSERR);
954    }
955#endif
956    if (Status == 0)
957        /*
958         * It's definetely a CDROM.
959         */
960        DevInfo = CreateCDROM(ProbeData, DevName, CDspeed);
961    else if (DevDefine->Type == DT_DISKDRIVE) {
962        /*
963         * It's a normal Disk Drive.
964         */
965        if ((dk_vtoc = GETvtoc(fd, DevFile)) == NULL)
966            SImsg(SIM_GERR, "%s: get vtoc failed.", DevFile);
967        if ((dk_cinfo = GETdk_cinfo(fd, DevFile)) == NULL)
968            SImsg(SIM_GERR, "%s: get dk_cinfo failed.", DevFile);
969        if ((dk_geom = GETdk_geom(fd, DevFile)) == NULL)
970            SImsg(SIM_GERR, "%s: get dk_geom failed.", DevFile);
971#if     defined(HAVE_HDIO)
972        if ((dk_type = GETdk_type(fd, DevFile)) == NULL)
973            SImsg(SIM_DBG, "%s: no dk_type info available.", DevFile);
974#endif  /* HAVE_HDIO */
975
976        DevInfo = CreateDiskDrive(ProbeData, DevName,
977                                  dk_vtoc, dk_cinfo, dk_geom, dk_type);
978        if (!DevInfo)
979            SImsg(SIM_GERR, "%s: Cannot convert DiskDrive information.",
980                  DevName);
981    }
982    if (!DevInfo)
983        /*
984         * If we still haven't gotten any information on what type of
985         * DiskDrive this really is, create a basic entry anyway.
986         */
987        DevInfo = CreateBaseDiskDrive(ProbeData, DiskName);
988
989    close(fd);
990    ProbeData->FileDesc = -1;
991
992    return(ProbeData->RetDevInfo = DevInfo);
993}
994
995/*
996 * Probe a disk drive by general name (DiskName)
997 */
998extern DevInfo_t *ProbeDiskDrive(ProbeData)
999     ProbeData_t               *ProbeData;
1000{
1001    char                      **FileList;
1002    int                         FileCount;
1003    register int                i;
1004    char                       *DiskName;
1005
1006    if (!ProbeData || !(DiskName = ProbeData->DevName))
1007        return((DevInfo_t *)NULL);
1008
1009    FileCount = GetDeviceFile(ProbeData, _PATH_DEV_RDSK, &FileList);
1010    if (FileCount < 1) {
1011        SImsg(SIM_GERR, "Cannot find disk device file for <%s>.", DiskName);
1012        return((DevInfo_t *)NULL);
1013    }
1014
1015    for (i = 0; i < FileCount; ++i) {
1016        ProbeData->DevFile = FileList[i];
1017        if (DevInfo = ProbeDiskDriveFile(ProbeData, FALSE))
1018            return(ProbeData->RetDevInfo = DevInfo);
1019    }
1020
1021    return((DevInfo_t *)NULL);
1022}
1023
1024/*
1025 * Probe a Floppy device referenced by ProbeData->DevFile.
1026 * UsingVolMgt means we're using VolMgt on this call.
1027 */
1028static DevInfo_t *ProbeFloppyFile(ProbeData, UsingVolMgt)
1029     ProbeData_t               *ProbeData;
1030     int                        UsingVolMgt;
1031{
1032    DevInfo_t                  *DevInfo = NULL;
1033    static struct fd_char       FDchar;
1034    static struct fd_drive      FDdrive;
1035    char                       *DevName;
1036    int                         fd;
1037    char                       *VolDevFile = NULL;
1038    char                       *DevFile;
1039    DevData_t                  *DevData;
1040    DevDefine_t                *DevDefine;
1041    DiskDriveData_t            *DiskDriveData = NULL;
1042    DiskDrive_t                *Disk = NULL;
1043
1044    if (!ProbeData || !ProbeData->DevFile)
1045        return((DevInfo_t *)NULL);
1046
1047    DevFile = ProbeData->DevFile;
1048    DevData = ProbeData->DevData;
1049    DevDefine = ProbeData->DevDefine;
1050    DevData->DevType = DT_FLOPPY;
1051
1052    /*
1053     * Try opening the disk device.  Usually this will be the "s0" device.
1054     * If that fails, try opening "s2".  Sometimes there's no "s0"
1055     * partition, but there is an "s2".
1056     *
1057     * The O_NDELAY flag will allow the device to be opened even if no
1058     * media is loaded.
1059     */
1060    fd = open(DevFile, O_RDONLY|O_NDELAY|O_NONBLOCK);
1061    ProbeData->FileDesc = fd;
1062    if (fd < 0) {
1063        SImsg(SIM_GERR, "%s: Cannot open for reading: %s.", DevFile, SYSERR);
1064#if     defined(HAVE_VOLMGT)
1065        if (errno == EBUSY && !UsingVolMgt) {
1066            /*
1067             * The device is busy, so let's try acquiring the device from
1068             * the Volume Manager.  If that succeeds, call this function
1069             * again, but use the Vol Manager device pathname.
1070             */
1071            if (VolDevFile = VolMgtAcquire(ProbeData)) {
1072                ProbeData->DevFile = VolDevFile;
1073                DevInfo = ProbeDiskDriveFile(ProbeData, TRUE);
1074                ProbeData->UseDevInfo = DevInfo;
1075                VolMgtGetAttr(ProbeData);
1076                VolMgtRelease(VolDevFile);
1077                return(DevInfo);
1078            }
1079        }
1080#endif  /* HAVE_VOLMGT */
1081        if (errno == EBUSY ||
1082            ((DevDefine->Model || DevDefine->Desc || DevData->DevNum > 0) &&
1083             FLAGS_ON(DevData->Flags, DD_IS_ALIVE))) {
1084            /*
1085             * If we know for sure this drive is present and we
1086             * know something about it, then create a minimal device.
1087             */
1088            return(DeviceCreate(ProbeData));
1089        }
1090        return((DevInfo_t *) NULL);
1091    }
1092
1093    if (!DevInfo)
1094        DevInfo = DeviceCreate(ProbeData);
1095
1096    (void) memset(&FDchar, 0, sizeof(FDchar));
1097    if (ioctl(fd, FDIOGCHAR, &FDchar) < 0) {
1098        SImsg(SIM_DBG, "%s: ioctl FDIOGCHAR failed: %s", DevFile, SYSERR);
1099    } else {
1100        /* Setup Disk info */
1101        if (DevInfo->DevSpec)
1102            DiskDriveData = (DiskDriveData_t *) DevInfo->DevSpec;
1103        else {
1104            DiskDriveData = NewDiskDriveData(NULL);
1105            DevInfo->DevSpec = (void *) DiskDriveData;
1106        }
1107        if (DiskDriveData->HWdata)
1108            Disk = DiskDriveData->HWdata;
1109        else {
1110            Disk = NewDiskDrive(NULL);
1111            DiskDriveData->HWdata = Disk;
1112        }
1113        /* Set what we got */
1114        Disk->Tracks = FDchar.fdc_nhead;
1115        Disk->SecSize = FDchar.fdc_sec_size;
1116        Disk->Sect = FDchar.fdc_secptrack;
1117        Disk->DataCyl = FDchar.fdc_ncyl;
1118        Disk->StepsPerTrack = FDchar.fdc_steps;
1119        if (FDchar.fdc_transfer_rate > 0)
1120            AddDevDesc(DevInfo, itoa(FDchar.fdc_transfer_rate),
1121                       "Transfer Rate (Kb/s)", DA_APPEND);
1122    }
1123
1124    (void) memset(&FDdrive, 0, sizeof(FDdrive));
1125    if (ioctl(fd, FDGETDRIVECHAR, &FDdrive) < 0) {
1126        SImsg(SIM_DBG, "%s: ioctl FDGETDRIVECHAR failed: %s", DevFile, SYSERR);
1127    } else {
1128        if (FDdrive.fdd_ejectable > 0)
1129            AddDevDesc(DevInfo, "Manual Eject", "Has", DA_APPEND);
1130        if (FDdrive.fdd_maxsearch > 0)
1131            AddDevDesc(DevInfo, itoa(FDdrive.fdd_maxsearch),
1132                       "Size of per unit search table", DA_APPEND);
1133        if (FDdrive.fdd_writeprecomp > 0)
1134            AddDevDesc(DevInfo, itoa(FDdrive.fdd_writeprecomp),
1135                       "Precompensation start cylinder", DA_APPEND);
1136        if (FDdrive.fdd_writereduce > 0)
1137            AddDevDesc(DevInfo, itoa(FDdrive.fdd_writereduce),
1138                       "Reduce write current start cylinder", DA_APPEND);
1139        if (FDdrive.fdd_stepwidth > 0)
1140            AddDevDesc(DevInfo, itoa(FDdrive.fdd_stepwidth),
1141                       "Width of step pulse (1us)", DA_APPEND);
1142        if (FDdrive.fdd_steprate > 0)
1143            AddDevDesc(DevInfo, itoa(FDdrive.fdd_steprate),
1144                       "Step Rate (100us)", DA_APPEND);
1145        if (FDdrive.fdd_headsettle > 0)
1146            AddDevDesc(DevInfo, itoa(FDdrive.fdd_headsettle),
1147                       "Head settle delay (100us)", DA_APPEND);
1148        if (FDdrive.fdd_headload > 0)
1149            AddDevDesc(DevInfo, itoa(FDdrive.fdd_headload),
1150                       "Head load delay (100us)", DA_APPEND);
1151        if (FDdrive.fdd_headunload > 0)
1152            AddDevDesc(DevInfo, itoa(FDdrive.fdd_headunload),
1153                       "Head unload delay (100us)", DA_APPEND);
1154        if (FDdrive.fdd_motoron > 0)
1155            AddDevDesc(DevInfo, itoa(FDdrive.fdd_motoron),
1156                       "Motor On delay (100us)", DA_APPEND);
1157        if (FDdrive.fdd_motoroff > 0)
1158            AddDevDesc(DevInfo, itoa(FDdrive.fdd_motoroff),
1159                       "Motor Off delay (100us)", DA_APPEND);
1160        if (FDdrive.fdd_precomplevel > 0)
1161            AddDevDesc(DevInfo, itoa(FDdrive.fdd_precomplevel),
1162                       "Pre Comp Level (ns)", DA_APPEND);
1163    }
1164
1165    close(fd);
1166    ProbeData->FileDesc = -1;
1167
1168    return(ProbeData->RetDevInfo = DevInfo);
1169}
1170
1171/*
1172 * Probe a floppy disk drive
1173 */
1174extern DevInfo_t *ProbeFloppy(ProbeData)
1175     ProbeData_t               *ProbeData;
1176{
1177    char                      **FileList;
1178    int                         FileCount;
1179    register int                i;
1180    char                       *DevName;
1181
1182    if (!ProbeData || !(DevName = ProbeData->DevName))
1183        return((DevInfo_t *)NULL);
1184
1185    FileCount = GetDeviceFile(ProbeData, _PATH_DEV_RDSK, &FileList);
1186    if (FileCount < 1) {
1187        SImsg(SIM_GERR, "%s: Cannot find floppy device file.", DevName);
1188        return((DevInfo_t *)NULL);
1189    }
1190
1191    for (i = 0; i < FileCount; ++i) {
1192        ProbeData->DevFile = FileList[i];
1193        if (DevInfo = ProbeFloppyFile(ProbeData, FALSE))
1194            return(ProbeData->RetDevInfo = DevInfo);
1195    }
1196
1197    return((DevInfo_t *)NULL);
1198}
1199
1200/*
1201 * Get hostid
1202 */
1203long gethostid()
1204{
1205    char                        Buff[64];
1206
1207    sysinfo(SI_HW_SERIAL, Buff, sizeof(Buff));
1208
1209    return(atol(Buff));
1210}
1211
1212/*
1213 * Get system page size
1214 */
1215int getpagesize()
1216{
1217    long                        siz;
1218
1219    if ((siz = sysconf(_SC_PAGESIZE)) == -1) {
1220        SImsg(SIM_GERR, "Cannot get pagesize from sysconf(): %s", SYSERR);
1221        return(0);
1222    }
1223
1224    return((int) siz);
1225}
1226
1227#if     defined(HAVE_SUNROMVEC)
1228#include <sys/comvec.h>
1229#endif  /* HAVE_SUNROMVEC */
1230
1231/*
1232 * Get ROM Version number
1233 */
1234extern char *GetRomVerSun()
1235{
1236    static char                 RomRev[32];
1237#if     defined(HAVE_SUNROMVEC)
1238    struct nlist               *nlptr;
1239    static union sunromvec      Rom;
1240    kvm_t                      *kd;
1241    union sunromvec            *romp;
1242
1243    if (!(kd = KVMopen()))
1244        return((char *) NULL);
1245
1246    if ((nlptr = KVMnlist(kd, RomVecSYM, (struct nlist *)NULL, 0)) == NULL)
1247        return((char *) NULL);
1248
1249    if (CheckNlist(nlptr))
1250        return((char *) NULL);
1251
1252    /*
1253     * Read the kernel pointer to the sunromvec structure.
1254     */
1255    if (KVMget(kd, (u_long) nlptr->n_value, (char *) &romp,
1256               sizeof(romp), KDT_DATA)) {
1257        SImsg(SIM_GERR, "Cannot read sunromvec pointer from kernel.");
1258        return((char *) NULL);
1259    }
1260
1261    /*
1262     * Read sunromvec from the kernel
1263     */
1264    if (KVMget(kd, (u_long) romp, (char *) &Rom,
1265               sizeof(union sunromvec), KDT_DATA)) {
1266        SImsg(SIM_GERR, "Cannot read sunromvec from kernel.");
1267        return((char *) NULL);
1268    }
1269
1270    if (Rom.sunmon.v_mon_id) {
1271        /*
1272         * Read the version string from the address indicated by v_mon_id.
1273         * Read 1 byte at a time until '\0' is encountered.
1274         */
1275        if (KVMget(kd, (u_long) Rom.sunmon.v_mon_id, RomRev,
1276                   sizeof(RomRev), KDT_STRING)) {
1277            SImsg(SIM_GERR, "Cannot read sunmon rom revision from kernel.");
1278            return((char *) NULL);
1279        }
1280    }
1281
1282    if (Rom.obp.op_mon_id && !RomRev[0]) {
1283        /*
1284         * XXX Hardcoded values
1285         */
1286        (void) snprintf(RomRev, sizeof(RomRev),  "%d.%d",
1287                       Rom.obp.op_mon_id >> 16, Rom.obp.op_mon_id & 0xFFFF);
1288    }
1289
1290    KVMclose(kd);
1291
1292#endif  /* HAVE_SUNROMVEC */
1293
1294    return((RomRev[0]) ? RomRev : (char *) NULL);
1295}
1296
1297/*
1298 * Get amount of physical memory using sysmem() call.
1299 */
1300extern char *GetMemorySunOSsysmem()
1301{
1302    char                       *Val = NULL;
1303#if     defined(USE_SYSMEM)
1304    /*
1305     * sysmem() is an undocumented function that returns the
1306     * amount of system (physical) memory in bytes.  It's in
1307     * /usr/lib/libadm.a.  Discovered by reference in Sun
1308     * PatchID 101050-01.
1309     *
1310     * NOTE: sysmem() is broken in SunOS 5.5 and 5.5.1 so we avoid it.
1311     */
1312    long                        Amount;
1313
1314    Amount = sysmem();
1315    if (Amount < 0) {
1316        SImsg(SIM_GERR, "sysmem() failed: %s", SYSERR);
1317        return((char *) NULL);
1318    }
1319
1320    Val = GetMemoryStr(DivRndUp(Amount, (Large_t) MBYTES));
1321#endif  /* USE_SYSMEM */
1322    return(Val);
1323}
1324
1325/*
1326 * Get amount of physical memory using sysconf()
1327 */
1328extern char *GetMemorySunOSsysconf()
1329{
1330    char                       *Val = NULL;
1331#if     defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
1332    long long                   Amount;
1333    long                        PageSize;
1334    long                        NumPages;
1335
1336    PageSize = sysconf(_SC_PAGESIZE);
1337    NumPages = sysconf(_SC_PHYS_PAGES);
1338    if (PageSize < 0 || NumPages < 0) {
1339      SImsg(SIM_GERR, "sysconf() failed: %s", SYSERR);
1340      return((char *) NULL);
1341    }
1342    Amount = (long long) PageSize * NumPages;
1343
1344    Val = GetMemoryStr((int) ((Amount+MBYTES-1) / MBYTES), MBYTES);
1345#endif  /* _SC_* */
1346    return(Val);
1347}
1348
1349/*
1350 * Get the system to detect all disk drives on the system.
1351 * We only open the "s2" file for each device to avoid a
1352 * performance hit of opening every device file.
1353 */
1354static void DetectDisks()
1355{
1356    static DIR                 *DirPtr;
1357    struct dirent              *DirEnt;
1358    static char                 DevName[MAXPATHLEN];
1359    static char                 PathName[MAXPATHLEN];
1360    static namelist_t          *UsedList = NULL;
1361    register char              *cp;
1362    int                         FileD;
1363
1364    if (!(DirPtr = opendir(_PATH_DEV_RDSK))) {
1365        SImsg(SIM_GERR, "Cannot open directory %s: %s.",
1366              _PATH_DEV_RDSK, SYSERR);
1367        return;
1368    }
1369
1370    while (DirEnt = readdir(DirPtr)) {
1371        if (EQ(DirEnt->d_name, ".") || EQ(DirEnt->d_name, ".."))
1372            continue;
1373
1374        (void) strcpy(DevName, DirEnt->d_name);
1375        if (cp = strchr(DevName, 's'))
1376            *cp = CNULL;
1377        if (NameListFind(UsedList, DevName))
1378            continue;
1379
1380        /*
1381         * Always use slice 2 which should always
1382         * have a partition table.
1383         */
1384        (void) snprintf(PathName, sizeof(PathName),  "%s/%ss2", _PATH_DEV_RDSK, DevName);
1385        if ((FileD = open(PathName, O_RDONLY)) > 0)
1386            (void) close(FileD);
1387        NameListAdd(&UsedList, DevName);
1388    }
1389
1390    NameListFree(UsedList);
1391    (void) closedir(DirPtr);
1392}
1393
1394/*
1395 * Get the system to detect all tape drives on the system.
1396 */
1397static void DetectTapes()
1398{
1399    static DIR                 *DirPtr;
1400    struct dirent              *DirEnt;
1401    static char                 DevName[MAXPATHLEN];
1402    static char                 PathName[MAXPATHLEN];
1403    static namelist_t          *UsedList = NULL;
1404    register char              *cp;
1405    int                         FileD;
1406
1407    if (!(DirPtr = opendir(_PATH_DEV_RMT))) {
1408        SImsg(SIM_GERR, "Cannot open directory %s: %s.",
1409              _PATH_DEV_RMT, SYSERR);
1410        return;
1411    }
1412
1413    while (DirEnt = readdir(DirPtr)) {
1414        if (EQ(DirEnt->d_name, ".") || EQ(DirEnt->d_name, ".."))
1415            continue;
1416
1417        (void) strcpy(DevName, DirEnt->d_name);
1418        for (cp = DevName; cp && isdigit(*cp); ++cp);
1419        if (cp)
1420            *cp = CNULL;
1421        if (NameListFind(UsedList, DevName))
1422            continue;
1423
1424        /*
1425         * Always use the "n" device to avoid rewinding the tape.
1426         */
1427        (void) snprintf(PathName, sizeof(PathName),  "%s/%sn", _PATH_DEV_RMT, DevName);
1428        if ((FileD = open(PathName, O_RDONLY)) > 0)
1429            (void) close(FileD);
1430        NameListAdd(&UsedList, DevName);
1431    }
1432
1433    NameListFree(UsedList);
1434    (void) closedir(DirPtr);
1435}
1436
1437/*
1438 * Get the system to detect the floppy disk drive.
1439 */
1440static int DetectFloppy()
1441{
1442    static char                 DevName[MAXPATHLEN];
1443    int                         FileD;
1444
1445    (void) snprintf(DevName, sizeof(DevName),  "%s/rdiskette", _PATH_DEV);
1446    if ((FileD = open(DevName, O_RDONLY)) > 0)
1447        (void) close(FileD);
1448}
1449
1450/*
1451 * The system does not "see" all devices until something attempts
1452 * to first use them.  These routines will cause the system to look
1453 * for and "see" certain devices that are not normally seen after
1454 * a system boot.
1455 */
1456extern void DetectDevices()
1457{
1458    DetectDisks();
1459    DetectTapes();
1460    DetectFloppy();
1461}
1462
1463/*
1464 * There's no easy way to get this out of /kernel/unix so we
1465 * do the same thing the kernel does.
1466 */
1467extern char *GetKernVerSunOS5()
1468{
1469    static char                 Buff[128];
1470    static struct utsname       un;
1471
1472    if (uname(&un) == -1)
1473        return((char *) NULL);
1474
1475    (void) snprintf(Buff, sizeof(Buff), 
1476           "SunOS Release %s Version %s%s [UNIX(R) System V Release 4.0]",
1477                   un.release, un.version,
1478#ifdef _LP64
1479                   " 64-bit"
1480#else
1481                   ""
1482#endif
1483                   );
1484
1485    return(Buff);
1486}
1487
1488/*
1489 * Get the OS Dist information by reading the first line of /etc/release
1490 */
1491extern char *GetOSDistSunOS5()
1492{
1493#if     defined(OS_RELEASE_FILE)
1494    static char                 Buff[256];
1495    FILE                       *fp;
1496    register char              *cp;
1497
1498    fp = fopen(OS_RELEASE_FILE, "r");
1499    if (!fp) {
1500        SImsg(SIM_GERR, "%s: Cannot open OS release file: %s",
1501              OS_RELEASE_FILE, SYSERR);
1502        return((char *) NULL);
1503    }
1504
1505    if (!fgets(Buff, sizeof(Buff), fp)) {
1506        SImsg(SIM_GERR, "%s: Read OS release file failed: %s",
1507              OS_RELEASE_FILE, SYSERR);
1508        return((char *) NULL);
1509    }
1510    (void) fclose(fp);
1511
1512    /* Zap trailing newline */
1513    if (cp = strchr(Buff, '\n'))
1514        *cp = CNULL;
1515
1516    /* Skip leading white space */
1517    for (cp = Buff; isspace(*cp); ++cp);
1518
1519    return(cp);
1520#endif  /* OS_RELEASE_FILE */
1521}
Note: See TracBrowser for help on using the repository browser.