/********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ static char Sccsid[] = "@(#)rax1.c 3.1 3/26/87"; /* * ULTRIX-11 UDA50 - RA60/RA80/RA81 disk exerciser program (rax). * KDA50 - RA60/RA80/RA81 * RQDX1/2 - RD31/RD32/RD51/RD52/RD53/RD54/RX50/RX33 * RQDX3 - RD31/RD32/RD51/RD52/RD53/RD54/RX50/RX33 * RUX1 - RX50 * KLESI - RC25 * * PART 1 - (rax1.c) * * Part 1 does the initial setup and argument processing, * writes the results into a file `rax_#.arg' (# = drive). * and then calls part 2 of rax, which is the actual exerciser. * The program is split into two sections to optimize * memory usage. * * Fred Canter * Bill Burns 4/84 * added check for overlapping filesystems * added -x option for rx50/rx33 (forces -w to raxr and ensures * that the device is indeed an rx50/rx33. * added event flag code * * ********************************************* * * * * * This program will not function correctly * * * unless the current ULTRIX-11 monitor file * * * is named "unix". * * * * * ********************************************* * * This program exercises the following disks: * RC25 RA60 RA80 RA81 RX50 RX33 RD31 RD32 RD51 RD52 RD53 RD54 * via the ULTRIX-11 block and raw I/O interfaces, at * the user level. * It reports the occurrence of hard errors and/or data * compare errors on the standard output. * The detailed device error information must be obtained * the system error log (elp -ra). * * CHANGES FOR USER SETABLE DISK PARTITIONS -- Fred Canter 7/5/85 * * The disk partition sizes table in the currently running kernel is * compared with the standard sizes table, and the operation of RAX * is modified accordingly. The standard sizes table is hard coded * into the RA exerciser via "#include /usr/sys/conf/dksizes.c". * * If the sizes tables match, then RAX allows full functionality, i.e, * it knows the disk layout and can protect the user from him/her self. * * If the sizes tables don't match, it is assumed that the user changed * the partition layout for some reason, and RAX operation is modified * as follows: * * 1. If the user changed partition 7, fatal error exit. * * 2. If any partition, other than 7, overlaps the maintenance * area, fatal error exit. * * 3. If the disk is the system disk (root, swap, error log) or * has any mounted file systems, then RAX will only write in * the maintenance area. The rest of the disk is read only. * * 4. If the disk is not the system disk and has no mounted file * systems, then partition 7 will be a free fire zone. Only * partition 7 will be used. * * 5. The -f flag is ignored. * * Note - Absence of the -w flag will also limit access to the * maintenance area. * * USAGE: * * rax -h * * Print the help message. * * * rax [-c#] [-d#] [-f#] [-m] [-s#] [-i] [-n #] [-e #] [-w] [-z #] * * Exercise the disk(s), using random addresses, * random byte counts, and alternating worst case * and random data patterns. * * [-z #] - event flag bit position, used to start/stop * exercisers * * [-c#] - MSCP controller number where drive connected (default=0) * * [-d#] - Select the drive to be exercised. * Only one drive may be selected. * * [-f#] - Select a file system to be exercised. * If multiple file systems are selected * only the lowest numbered one will be exercised. * * [-m] - Print the disk file system layout. * * [-s#] - Specify time intervals for periodic I/O statistics printouts. * The time interval (#) is in minutes and can range * from 1 to 720 (12 hours). * The default time interval is 1/2 hour. * If no time interval is specified (-s only), * the I/O statistics are not printed. * * [-i] - Inhibit the file system status printouts. * * [-n #] - Specify the number (#) of data mismatch errors * to be printer per failing block. * The maximum is 256 and the default is 5. * * [-e #] - Drop the disk after # hard errors, * default = 100, maximum = 1000. * * [-x] - Specifies that the drive to be tested is an RX50/RX33. * Forces -w option to be asserted, and causes a check * to make sure the drive is indeed an RX50/RX33. * * [-w] - Allow writes to the customer area of a winchester * disks: RA60/RA80/RA81, RC25, & RD31/RD32/RD51/RD52/RD53/RD54. * Normally writes are only allowed on the maintenance area. * * note - The root, swap, error log, and any mounted file * systems are automatically write protected. * If any file systems on the selected drive * are marked read only then any overlapping * file systems are also marked read only. * * EXAMPLE: * rax -c0 -d1 -m * * Print the file system map and exercise all * file systems on controller 0 drive 1. * * */ #include <sys/param.h> #include <sys/devmaj.h> #include <sys/mount.h> #include <sys/ra_info.h> #define USEP 1 #define NUDA 1 #include "/usr/sys/conf/dksizes.c" #include <stdio.h> #include <a.out.h> #include <signal.h> /* * Structure for accessing symbols in the ULTRIX-11 kernel * via the nlist subroutine and the /dev/mem driver. */ struct nlist nl[] = { { "_ra_size" }, { "_rootdev" }, { "_swapdev" }, { "_swplo" }, { "_nswap" }, { "_el_dev" }, { "_el_sb" }, { "_el_nb" }, { "_cputype" }, { "_nmount" }, { "_usermem" }, { "_ra_drv" }, { "_mount" }, { "ova" }, { "_ra_ctid" }, { "_ra_mas" }, { "_nuda" }, { "_ra_inde" }, { "" }, }; /* * The following are the symbols who's values are obtained * from the ULTRIX-11 kernel. * THE ORDER MUST NOT BE CHANGED ! */ int rootdev; int swapdev; int swplo; int nswap; int el_dev; int el_sb; int el_nb; int cputype; int nmount; int usermem; /* * Text array used by the print file * system read only status code. */ char *fsutab[] = { "dummy", "root", "swap", "error log", "mounted", "overlapping", "not maintenance", 0 }; /* * Control variables for dealing with user * setable disk partitions. */ int nsdp; /* non-standard disk partition layout being used */ int dpmask; /* bitwise 1 = partition used by drive being exericsed */ /* * File system layout, also * obtained from the ULTRIX-11 kernel. * * Prototype sizes tables now in /usr/sys/conf/dksizes.c */ struct rasize rasizes[8]; int ra_saddr[MAXUDA]; /* address of driver sizes table */ int nuda; /* Number of MSCP controllers configured */ daddr_t ra_mas[MAXUDA]; /* maint area size UDA=1000, RQDX=32, KLESI=102 */ char ra_ctid[MAXUDA]; /* RA controller type IDs (see ra.c) */ char ra_index[MAXUDA]; /* index into non-semetrical arrays */ /* * Overlapping partition array, * set dynamically by examining the sizes table. */ int ovp[8]; /* * Controller and unit number. */ int cn = 0; int dn = -1; struct ra_drv ra_drv[8]; /* * drive can be opened flag. */ int ra_opn; /* * Selected file system array. * Element = 0 for file system not selected. * Element = 1 for file system selected. */ char fsact[] {0, 0, 0, 0, 0, 0, 0, 0}; /* * File system write read status array. * element is zero for write/read access * element is non zero for read only access */ char fswrs[8]; /* * block and raw I/O file name. */ char fn[20]; /* * Armument file name */ char afn[] = "rax0_0.arg"; /* * Help message. */ char *help[] { "\n\n(rax) - ULTRIX-11 UDA50/KDA50/RQDX1/RQDX3/RUX1/KLESI disk exerciser.", "\nUsage:\n", "\trax [-h] [-c#] [-d#] [-f#] [-m] [-s#] [-i] [-n #] [-e #]", "\n-h\tPrint this help message", "\n-c#\tMSCP controller number `#' (default = 0) ", "\n-d#\tSelect drive number `#' ", "\n-f#\tExercise only file system `#'", "\n-m\tPrint file system layout", "\n-s#\tPrint I/O statistics every `#' minutes (default = 30 minutes)", "\n-s\tInhibit I/O statistics printout", "\n-i\tInhibit file system write/read status printout", "\n-n #\tLimit number of data compare error printouts to `#'", "\n-e #\tDrop the disk after # errors, default = 100, maximum = 1000", "\n-w\tCAUTION! - Allows writes to customer area of fixed media disks.", "\n\n", 0 }; /* * Time buffers. */ int istime = 30; char argbuf[512]; int fflag, mflag, sflag, iflag, wflag, xflag; int ndep = 5; int ndrop = 100; #ifdef EFLG char *efbit; char *efids; int zflag; #else char *killfn = "rax.kill"; #endif main(argc, argv) char *argv[]; int argc; { int stop(), intr(); register struct mount *mtp; register char *p; register int i; int *ap; int j, k; int fd; char *n; char c; char *mp; int mem; int a, b; int x, y; int ronly; int bufsiz; int bcmask; struct rasize *spp; daddr_t i_sb, i_eb, j_sb, j_eb; setpgrp(0, 31111); signal(SIGTTOU, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGQUIT, stop); if(argc < 2) goto aderr; for(i=1; i < argc; i++) { /* decode arg's */ p = argv[i]; if(*p++ != '-') { aderr: fprintf(stderr,"\nrax: bad arg\n"); exit(1); } switch(*p) { case 'h': /* print help message */ for(j=0; help[j]; j++) fprintf(stderr,"\n%s",help[j]); exit(); #ifdef EFLG case 'z': zflag++; i++; efbit = argv[i++]; efids = argv[i]; break; #else case 'r': /* kill filename */ i++; killfn = argv[i]; break; #endif case 'd': /* select drive */ p++; if(*p < '0' || *p > '7') goto aderr; dn = *p - '0'; afn[5] = *p; /* argument file name */ break; case 'c': /* select controller */ p++; if(*p < '0' || *p > '3') goto aderr; cn = *p - '0'; afn[3] = *p; /* argument file name */ break; case 'f': /* select file system */ fflag++; p++; if(*p < '0' || *p > '7') goto aderr; fsact[*p - '0']++; break; case 'm': /* print file system map */ mflag++; break; case 'n': /* # of data errors to print */ i++; ndep = atoi(argv[i]); if((ndep <= 0) || (ndep > 256)) ndep = 5; break; case 'e': /* drop disk after # errors */ i++; ndrop = atoi(argv[i]); if((ndrop <= 0) || (ndrop > 1000)) ndrop = 100; break; case 'i': /* Inhibit file system status printouts */ iflag++; break; case 's': sflag++; p++; if(*p < '0' || *p >'9') break; sflag = 0; istime = atoi(p); if(istime <= 0) istime = 30; if(istime > 720) istime = 720; break; case 'x': xflag++; wflag++; break; case 'w': /* write to customer area */ wflag++; break; default: /* bad argument */ goto aderr; } } if(!zflag) { if(isatty(2)) { fprintf(stderr,"rax: detaching... type \"sysxstop\" to stop\n"); fflush(stderr); } if((i = fork()) == -1) { printf("rax: Can't fork new copy !\n"); exit(1); } if(i != 0) exit(0); } setpgrp(0, 31111); /* * Check for invalid option combinatons & defaults. */ if((dn < 0) && ((argc != 2) && (!mflag))) { fprintf(stderr, "\nrax: must select drive\n"); exit(1); } if(!fflag) { for(j=0; j<8; j++) fsact[j]++; } /* * Use the nlist subroutine & /dev/mem to set the values * to obtain needed data from the ULTRIX-11 kernel. */ nlist("/unix", nl); for(i=1; i<13; i++) { /* don't check size table */ if(i == 11) /* don't check drive type */ continue; if(nl[i].n_type == 0) { fprintf(stderr,"\nrax: Can't access namelist in /unix!\n"); exit(1); } } if((nl[11].n_type == 0) || (nl[0].n_type == 0) || (nl[16].n_type = 0) || (nl[17].n_type = 0) || (nl[14].n_type == 0) || (nl[15].n_type == 0)) { no_uda: fprintf(stderr, "\nrax: /unix not configured for MSCP disks!\n"); exit(1); } if((mem = open("/dev/mem", 0)) < 0) { fprintf(stderr,"\nrax: Can't open /dev/mem\n"); exit(1); } mp = &rootdev; for(i=1; i<11; i++) { lseek(mem, (long)nl[i].n_value, 0); read(mem, (char *)mp, sizeof(int)); mp += sizeof(int); } /* * Get number and type of MSCP controllers. */ lseek(mem, (long)nl[16].n_value, 0); read(mem, (char *)&nuda, sizeof(nuda)); if(nuda == 0) goto no_uda; if(cn >= nuda) { printf("\nrax: /unix only configured for %d MSCP controller(s)\n", nuda); exit(1); } lseek(mem, (long)nl[17].n_value, 0); read(mem, (char *)&ra_index, MAXUDA); lseek(mem, (long)nl[14].n_value, 0); read(mem, (char *)&ra_ctid, MAXUDA); if(ra_ctid[cn] == 0) { printf("\nrax: MSCP controller %d not initialized!\n", cn); exit(1); } ra_ctid[cn] = (ra_ctid[cn] >> 4) & 017; /* * Get the disk file system layout * and maintenance area size. */ lseek(mem, (long)nl[0].n_value, 0); read(mem, (char *)&ra_saddr, sizeof(int) * nuda); lseek(mem, (long)ra_saddr[cn], 0); read(mem, (char *)&rasizes, sizeof(rasizes)); lseek(mem, (long)nl[15].n_value, 0); read(mem, (char *)&ra_mas, sizeof(long) * nuda); /* * Get the drive types. * Force open, then get them again. */ i = ra_index[cn] + dn; lseek(mem, (long)(nl[11].n_value+(i * sizeof(struct ra_drv))), 0); read(mem, (char *)&ra_drv[dn], sizeof(struct ra_drv)); /* * Attempt to open the first file system on selected drive, * if successful attempt to read first block of the file system. * This is done in order to force the disk driver to update * the ra_drv[] array with the unit size and on-line status of each unit. * This allows for drives to be enabled/disabled via the LAP * without requiring a reboot of the system. * This should not cause any errors to be logged. */ switch(ra_ctid[cn]) { case UDA50: case UDA50A: case KDA50: sprintf(&fn, "/dev/ra%o7", dn); /* file name */ if((a = open(fn, 0)) >= 0) if(read(a, (char *) &argbuf, 512) == 512) ra_opn++; close(a); break; case RQDX1: /* RD or RX */ case RQDX3: /* RD or RX */ sprintf(&fn, "/dev/rd%o7", dn); /* file name */ if((a = open(fn, 0)) >= 0) if(read(a, (char *) &argbuf, 512) == 512) ra_opn++; close(a); case RUX1: sprintf(&fn, "/dev/rx%o", dn); /* file name */ if((a = open(fn, 0)) >= 0) if(read(a, (char *) &argbuf, 512) == 512) ra_opn++; close(a); break; case KLESI: sprintf(&fn, "/dev/rc%o7", dn); /* file name */ if((a = open(fn, 0)) >= 0) if(read(a, (char *) &argbuf, 512) == 512) ra_opn++; close(a); break; default: break; /* unknown cntlr, ra_opn will be zero */ /* cntlr type validated later */ } i = ra_index[cn] + dn; lseek(mem, (long)(nl[11].n_value+(i * sizeof(struct ra_drv))), 0); read(mem, (char *)&ra_drv[dn], sizeof(struct ra_drv)); if(ra_drv[dn].ra_online == 0) ra_opn = 0; /* did not come on-line */ /* * Set the write and read buffer sizes * and transfer size limits, based on * the amount of user memory. */ if(usermem >= 4096) { /* 256 kb */ bufsiz = 8192; bcmask = 037776; } else { bufsiz = 4096; bcmask = 017776; } /* * Compare the prototype file system sizes table * with the real one, to insure that RAX really * does know about the disk layout. * Set the non-standard partitions flag if the sizes mismatch. */ switch(ra_ctid[cn]) { case RQDX1: case RQDX3: case RUX1: spp = &rq_sizes; break; case UDA50: case UDA50A: case KDA50: spp = &ud_sizes; break; case KLESI: spp = &rc_sizes; break; default: printf("\nrax: (%d) - unknown controller type !\n", ra_ctid[cn]); exit(1); } nsdp = 0; for(i=0; i<8; i++) if((rasizes[i].nblocks != spp[i].nblocks) || (rasizes[i].blkoff != spp[i].blkoff)) nsdp++; /* * If non-standard partitions being used, * do some checks to insure minimum sanity level * of the sizes table. * * Partition 7 must not have changed. * No partition, other than 7, may overlap the maint. area. */ if(nsdp) { printf("\n****** cntlr %d unit %d ", cn, dn); printf("non standard partition layout ******\n"); if((rasizes[7].blkoff != 0L) || (rasizes[7].nblocks != -1L)) { fprintf(stderr, "\nrax: fatal error - partition 7 changed!\n"); exit(1); } } if(nsdp && (ra_drv[dn].ra_dt != RX50) && (ra_drv[dn].ra_dt != RX33)) { i_sb = ra_drv[dn].d_un.ra_dsize - ra_mas[cn]; /* maint. area size */ for(j=0; j<7; j++) { /* 7 not checked */ j_eb = rasizes[j].blkoff + rasizes[j].nblocks; if(j_eb > i_sb) { /* partition overlaps maint. area */ fprintf(stderr, "\nrax: fatal error - partition %d ", j); fprintf(stderr, "overlaps maintenance area!\n"); exit(1); } } } /* * Set dpmask to show which partitions are used * by this type of disk. The dpmask is, for the most part, * ignored if non standard partitions in use. */ switch(ra_drv[dn].ra_dt) { case RC25: dpmask = 0237; break; case RX33: dpmask = 0200; break; case RX50: dpmask = 0200; break; case RD31: dpmask = 0341; break; case RD51: dpmask = 0221; break; case RD32: case RD52: case RD53: case RD54: dpmask = 0217; break; case RA60: dpmask = 0277; break; case RA80: dpmask = 0217; break; case RA81: dpmask = 0377; break; default: dpmask = 0; break; } /* * Check that the selected unit is an RX50/RX33 * if the xflag is set */ if(xflag && (ra_drv[dn].ra_dt != RX50) && (ra_drv[dn].ra_dt != RX33)) { fprintf(stderr, "\nrax: controller %d ", cn); fprintf(stderr, "unit %d not an RX50 or RX33!\n", dn); exit(1); } /* * Change all partitions with length of -1, * to actual size, i.e., size of entire volume * minus block offset of partition. * * If size is -2 also subtract maint. area size. */ for(i=0; i<8; i++) { if(rasizes[i].nblocks == -1L) rasizes[i].nblocks = ra_drv[dn].d_un.ra_dsize - rasizes[i].blkoff; else if(rasizes[i].nblocks == -2L) rasizes[i].nblocks = ((ra_drv[dn].d_un.ra_dsize - rasizes[i].blkoff) - ra_mas[cn]); } /* * Set up the overlapping partitions table. * Table is only used with standard partition layout. */ for(i=0; i<8; i++) { /* find overlapping partitions */ ovp[i] = 0; if((dpmask & (1 << i)) == 0) continue; /* non usable partition */ i_sb = rasizes[i].blkoff; i_eb = rasizes[i].blkoff + rasizes[i].nblocks - 1; for(j=0; j<8; j++) { if((dpmask & (1 << j)) == 0) continue; /* non usable partition */ if(j == i) continue; /* can't overlap itself */ j_sb = rasizes[j].blkoff; j_eb = rasizes[j].blkoff + rasizes[j].nblocks - 1; if(((i_sb >= j_sb) && (i_sb <= j_eb)) || ((i_eb >= j_sb) && (i_eb <= j_eb)) || ((j_sb >= i_sb) && (j_sb <= i_eb)) || ((j_eb >= i_sb) && (j_eb <= i_eb)) || ((j_sb <= i_eb) && (j_eb >= i_sb))) ovp[i] |= (1 << j); } } /* * debug: fprintf(stderr, "\nDEBUG: ovp = "); for(i=0; i<8; i++) fprintf(stderr, "%o ", ovp[i]); fprintf(stderr, "\n"); */ /* * Print the file system map if [-m] was specified. * Only print file systems used by this type of disk, unless * non standard partitions in use, then print all file systems. * Always, only print file system 7 for RX50/RX33. */ if(mflag) { switch(ra_ctid[cn]) { case UDA50: case UDA50A: fprintf(stderr, "\n\nUDA50 - RA60/RA80/RA81"); break; case KDA50: fprintf(stderr, "\n\nKDA50 - RA60/RA80/RA81"); break; case KLESI: fprintf(stderr, "\n\nKLESI - RC25"); break; case RQDX1: fprintf(stderr, "\n\nRQDX1 - "); fprintf(stderr, "RD31/RD32/RD51/RD52/RD53/RD54/RX50/RX33"); break; case RQDX3: fprintf(stderr, "\n\nRQDX3 - "); fprintf(stderr, "RD31/RD32/RD51/RD52/RD53/RD54/RX50/RX33"); break; case RUX1: fprintf(stderr, "\n\nRUX1 - RX50"); break; } fprintf(stderr, " file system layout\n"); fprintf(stderr, "\nfilsys\toffset\tlength\n"); for(i=0; i<8; i++) { if((nsdp == 0) && ((dpmask & (1 << i)) == 0)) continue; /* partition not used */ if(nsdp && (ra_drv[dn].ra_dt == RX50) && (i != 7)) continue; if(nsdp && (ra_drv[dn].ra_dt == RX33) && (i != 7)) continue; if(rasizes[i].nblocks) fprintf(stderr, "\n%d\t%D\t%D", i,rasizes[i].blkoff,rasizes[i].nblocks); } fprintf(stderr,"\n\n"); exit(0); } /* * Print the status of drives. */ j = 0; printf("\nController %d Unit %d - ", cn, dn); switch(ra_drv[dn].ra_dt) { case RC25: printf("RC25 - "); break; case RX33: printf("RX33 - "); break; case RX50: printf("RX50 - "); break; case RD31: printf("RD31 - "); break; case RD32: printf("RD32 - "); break; case RD51: printf("RD51 - "); break; case RD52: printf("RD52 - "); break; case RD53: printf("RD53 - "); break; case RD54: printf("RD54 - "); break; case RA60: printf("RA60 - "); break; case RA80: printf("RA80 - "); break; case RA81: printf("RA81 - "); break; default: break; } if(ra_drv[dn].ra_dt && ra_opn) { printf("accessible"); j++; } else if(ra_drv[dn].ra_dt && !ra_opn) printf("not accessible"); else printf("non existent\n\n"); if(j == 0) exit(1); /* * Initialize the file system write/read status array. * Mark the root, swap, error log, & any mount file systems * read only. * Also mark file system 7 read only if any other * file systems on the drive are read only. */ /* * Read the mount table from /unix. * * New stuff - mount table is now consistent between * kernels (ov and sep I&D) - Bill Burns 8/13/84 */ mtp = nl[12].n_value; lseek(mem, (long)mtp, 0); for(i=0; i<nmount; i++, mtp++) { p = &argbuf; p += (sizeof(struct mount) * i); read(mem, (char *)p, sizeof(struct mount)); } close(mem); for(i=0; i<8; i++) { /* check file systems for selected unit */ a = (cn << 6) | (dn << 3) | i; /* minor device number */ fswrs[i] = cfs(a); /* check file system status */ if(fswrs[i]) /* root, swap, error log ? */ continue; /* yes, then read only ! */ b = (RA_BMAJ << 8) | a; /* maj/min device */ for(mtp = &argbuf, j=0; j<nmount; mtp++, j++) if((mtp->m_bufp != NULL) && (mtp->m_dev == b)) { fswrs[i] = 4; /* file system mounted */ break; } } /* * Loop to check for overlapping disk partitions */ a = 0; for(j = 0; j < 8; j++) { a =+ fswrs[j]; if((fswrs[j] > 0) && (fswrs[j] < 5)) for(x = ovp[j], y = 0; y < 8; y++) if((x & (1 << y)) && (fswrs[y] == 0)) fswrs[y] = 5; } ronly = a; /* save number of read only file systems */ /* * If non standard partitions in use and any read only * file systems, for wflag = 0 (write only in maint. area). */ if(nsdp && ronly) wflag = 0; /* * If the wflag is not set, all file systems read only. */ if(wflag == 0) { for(j=0; j<8; j++) fswrs[j] = 6; ronly = 8; } /* * Unless the iflag is set, print the list * of read only file systems. */ if(!iflag) { c = 0; for(i=0; i<8; i++) { if(nsdp) break; if((dpmask & (1 << i)) == 0) continue; /* partition not used */ if(rasizes[i].nblocks == 0) continue; if(fswrs[i]) { if(!c++) { printf("\n\nRead only file systems."); printf("\n\nunit\tfile"); printf("\nnumber\tsystem\treason"); } printf("\n%d\t%d\t", dn, i); printf("%s",fsutab[fswrs[i]]); printf(" file system"); } } } if(wflag == 0) printf("\n\n****** Writing to maintenance area only ******\n"); if(nsdp && (wflag != 0)) { printf("\n\n****** Writing to file system 7 only "); printf("(non standard partitions used) ******\n"); } /* * Write needed date into a file `rax?_#.arg' (? = ctlr, # = drive), * and call part 2 of the RA exerciser (raxr). */ ap = &argbuf; *ap++ = cn; *ap++ = dn; *ap++ = ndep; *ap++ = ndrop; *ap++ = fflag; *ap++ = sflag; *ap++ = wflag; *ap++ = istime; *ap++ = ronly; *ap++ = bufsiz; *ap++ = bcmask; *ap++ = (int)ra_mas[cn]; *ap++ = ra_ctid[cn]; *ap++ = nsdp; *ap++ = dpmask; #ifdef EFLG *ap++ = zflag; #endif p = ap; n = &rasizes; for(i=0; i<sizeof(rasizes); i++) *p++ = *n++; n = &ra_drv; for(i=0; i<sizeof(ra_drv); i++) *p++ = *n++; for(i=0; i<sizeof(fsact); i++) *p++ = fsact[i]; for(i=0; i<sizeof(fswrs); i++) *p++ = fswrs[i]; if((fd = creat(afn, 0644)) < 0) { fprintf(stderr, "\nrax: Can't create %s file\n", afn); exit(1); } if(write(fd, (char *)&argbuf, 512) != 512) { fprintf(stderr, "\nrax: %s write error\n", afn); exit(1); } close(fd); fflush(stdout); signal(SIGQUIT, SIG_IGN); #ifdef EFLG if(zflag) execl("raxr", "raxr", afn, efbit, efids, (char *)0); else execl("raxr", "raxr", afn, (char *)0); #else execl("raxr", "raxr", afn, killfn, (char *)0); #endif fprintf(stderr, "\nrax: Can't exec raxr\n"); exit(1); } /* * Check file system and return 0 if it is writable, * otherwise return 1 if it is the root file system, * 2 if it is the swap file system, and 3 if it * is the error log file system. */ cfs(dev) { register int rm, sm, em; rm = (rootdev >> 8) & 0377; sm = (swapdev >> 8) & 0377; em = (el_dev >> 8) & 0377; if((rm == RA_BMAJ) && (dev == (rootdev & 0377))) return(1); if((sm == RA_BMAJ) && (dev == (swapdev & 0377))) return(2); if((em == RA_RMAJ) && (dev == (el_dev & 0377))) return(3); return(0); } stop() { exit(0); }