1 /* @(#)sinfo.c 1.39 13/04/30 Copyright 1988-2013 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)sinfo.c 1.39 13/04/30 Copyright 1988-2013 J. Schilling";
6 #endif
7 /*
8 * Copyright (c) 1988-2013 J. Schilling
9 */
10 /*
11 * The contents of this file are subject to the terms of the
12 * Common Development and Distribution License, Version 1.0 only
13 * (the "License"). You may not use this file except in compliance
14 * with the License.
15 *
16 * See the file CDDL.Schily.txt in this distribution for details.
17 * A copy of the CDDL is also available via the Internet at
18 * http://www.opensource.org/licenses/cddl1.txt
19 *
20 * When distributing Covered Code, include this CDDL HEADER in each
21 * file and include the License file CDDL.Schily.txt from this distribution.
22 */
23
24 #include <schily/param.h> /* Include various defs needed with some OS */
25 #include <schily/stdio.h>
26 #include <schily/standard.h>
27 #include <schily/unistd.h>
28 #include <schily/stdlib.h>
29 #include <schily/string.h>
30 #include <schily/time.h>
31 #include <schily/hostname.h>
32 #include <schily/schily.h>
33
34 /*#include <scg/scgcmd.h>*/
35
36 #include "fmt.h"
37
38 #include <scg/scsireg.h>
39 #include <scg/scsidefs.h>
40 #include <scg/scsitransp.h>
41
42 #include "scsicmds.h"
43
44 LOCAL long sibuf[8*1024/sizeof (long)];
45
46 extern char *Sbuf;
47 extern long Sbufsize;
48
49 /*
50 * The next two structures always contain
51 * Mototola / network byte order.
52 */
53 struct si_stamp {
54 u_long si_xtime; /* Reserve for year > 2038 */
55 u_long si_time; /* 'sformat' format time */
56 char si_serial[16]; /* Hardware serial */
57 char si_uname[16]; /* user name */
58 char si_hname[64]; /* host name */
59 char si_dname[64]; /* domain name */
60 };
61
62 struct sinfo {
63 u_long si_id; /* some id */
64 u_long si_magic; /* The magic to see if release >= 3.0 */
65 u_long si_release; /* The release (for later enhancements) */
66 u_long si_reformats; /* # of times the disk has been reformatted */
67 u_short si_ncyl; /* # of cyls (may be we need this for dos) */
68 u_short si_spt; /* # of sectors/track (see above) */
69 u_char si_nhead; /* # of heads (may be we need this for dos) */
70 u_char si_cres[3]; /* Fill up to long boundary */
71 u_long si_res[2]; /* Reserved for later enhancements */
72 struct si_stamp si_last; /* The data for the last format on this disk */
73 struct si_stamp si_first; /* Data for the first sformat on this disk */
74 };
75
76 #define SI_MAGIC 0x4A534348
77 #define SI_RELEASE 3
78
79 extern int autoformat;
80
81 LOCAL u_long sinfo_chksum __PR((SCSI *scgp, u_long *));
82 LOCAL void fill_blk __PR((SCSI *scgp, u_long *, u_long));
83 LOCAL void fill_sinfo __PR((SCSI *scgp, struct sinfo *sinfo));
84 LOCAL void fill_stamp __PR((struct si_stamp *stamp));
85 LOCAL void print_stamp __PR((FILE *f, const char *fmt, struct si_stamp *stamp));
86 LOCAL void sinfo_geom __PR((SCSI *scgp, struct disk *, long *, long *, long *));
87 EXPORT void print_sinfo __PR((FILE *, SCSI *scgp));
88 EXPORT BOOL read_sinfo __PR((SCSI *scgp, struct disk *, BOOL));
89 EXPORT BOOL write_sinfo __PR((SCSI *scgp, struct disk *));
90
91 /*
92 void
93 print_bk(dp, n)
94 struct disk *dp;
95 long n;
96 {
97 long cy;
98 long hd;
99 long se;
100 long sx;
101 long xx;
102
103 sx = dp->spt;
104 if (dp->tpz != 0)
105 sx -= dp->aspz/dp->tpz;
106 xx = sx * dp->nhead;
107 cy = 1 + n / xx;
108 hd = n % xx;
109 se = hd % sx;
110 hd /= sx;
111
112 printf("Cyl: %ld Head: %ld Sec: %ld\n", cy, hd, se);
113 }
114 */
115
116 LOCAL u_long
sinfo_chksum(scgp,lp)117 sinfo_chksum(scgp, lp)
118 SCSI *scgp;
119 register u_long *lp;
120 {
121 register u_long chksum;
122 register int i;
123
124 chksum = 0L;
125 for (i = scgp->cap->c_bsize/sizeof (u_long) - 1; --i >= 0; ) {
126 chksum ^= *lp++;
127 }
128 return (chksum);
129 }
130
131 LOCAL void
fill_blk(scgp,blk,v)132 fill_blk(scgp, blk, v)
133 SCSI *scgp;
134 u_long *blk;
135 register u_long v;
136 {
137 register u_long *lp;
138 register int i;
139
140 lp = blk;
141 srand((int)v);
142 for (i = scgp->cap->c_bsize/sizeof (u_long) - 1; --i >= 0; ) {
143 *lp++ = v;
144 v = rand();
145 }
146 }
147
148 LOCAL void
fill_sinfo(scgp,sinfo)149 fill_sinfo(scgp, sinfo)
150 SCSI *scgp;
151 struct sinfo *sinfo;
152 {
153 /* print_sinfo(stdout, scgp);*/
154 fill_blk(scgp, (u_long *)sinfo, 0);
155 sinfo->si_magic = SI_MAGIC;
156 sinfo->si_release = SI_RELEASE;
157 sinfo->si_reformats = 0;
158
159 sinfo->si_ncyl = 0;
160 sinfo->si_spt = 0;
161 sinfo->si_nhead = 0;
162
163 fill_stamp(&sinfo->si_first);
164 fill_stamp(&sinfo->si_last);
165
166 ((u_long *)sibuf)[scgp->cap->c_bsize/sizeof (u_long) - 1] =
167 sinfo_chksum(scgp, (u_long *)sinfo);
168 }
169
170 LOCAL void
fill_stamp(stamp)171 fill_stamp(stamp)
172 struct si_stamp *stamp;
173 {
174 struct timeval tv;
175 char *uname;
176
177 gettimeofday(&tv, (struct timezone *)0);
178 stamp->si_time = tv.tv_sec;
179 stamp->si_xtime = 0;
180
181 sprintf(stamp->si_serial, "%lX", (unsigned long)gethostid());
182
183 uname = getlogin();
184 if (uname == NULL)
185 uname = getenv("USER");
186 stamp->si_uname[0] = '\0';
187 if (uname != NULL)
188 strncpy(stamp->si_uname, uname, sizeof (stamp->si_uname));
189 stamp->si_uname[sizeof (stamp->si_uname)-1] = '\0';
190
191 gethostname(stamp->si_hname, sizeof (stamp->si_hname)-1);
192 stamp->si_hname[sizeof (stamp->si_hname)-1] = '\0';
193
194 getdomainname(stamp->si_dname, sizeof (stamp->si_dname)-1);
195 stamp->si_dname[sizeof (stamp->si_dname)-1] = '\0';
196 }
197
198 LOCAL void
print_stamp(f,fmt,stamp)199 print_stamp(f, fmt, stamp)
200 FILE *f;
201 const char *fmt;
202 struct si_stamp *stamp;
203 {
204 fprintf(f, "%s formatted with sformat id %s by:\n\t%s@%s%s%s on %s",
205 fmt,
206 stamp->si_serial,
207 stamp->si_uname, stamp->si_hname,
208 stamp->si_dname[0] == '.' ? "":".", stamp->si_dname,
209 asctime(localtime((time_t *)&stamp->si_time)));
210 }
211
212 LOCAL void
sinfo_geom(scgp,dp,sptp,aspzp,tpzp)213 sinfo_geom(scgp, dp, sptp, aspzp, tpzp)
214 SCSI *scgp;
215 struct disk *dp;
216 long *sptp; /* Sectors/Track */
217 long *aspzp; /* Alternate Sectors/Zone */
218 long *tpzp; /* Tracks/Zone */
219 {
220 if (dp->spt < 0 || dp->aspz < 0 || dp->tpz < 0) {
221 scgp->silent++;
222 dp->formatted++;
223 get_defaults(scgp, dp);
224 dp->formatted--;
225 scgp->silent--;
226 }
227 *sptp = dp->spt;
228 *aspzp = dp->aspz;
229 *tpzp = dp->tpz;
230 /*
231 * Wenn tpz == 0 (die ganze Platte ist eine Zone), dann wird
232 * aspz == 0 und tpz == 1, damit wird (spt - aspz/tpz) == spt,
233 * was der Realitaet entspricht.
234 */
235 if (dp->tpz == 0) {
236 *tpzp = 1L;
237 *aspzp = 0L;
238 }
239 /*
240 * Bei unbekannter Geometrie kommen der primaere und der sekundaere
241 * Sformat info Block direkt hintereinander: (spt - aspz/tpz) == 1.
242 */
243 if (dp->spt < 0 || dp->aspz < 0 || dp->tpz < 0) {
244 *sptp = *tpzp = 1L;
245 *aspzp = 0L;
246 }
247 }
248
249 EXPORT void
print_sinfo(f,scgp)250 print_sinfo(f, scgp)
251 FILE *f;
252 SCSI *scgp;
253 {
254 struct sinfo *sinfo = (struct sinfo *)sibuf;
255
256 fprintf(f, "Disk info:\n");
257 if (sinfo->si_id != 0)
258 fprintf(f, "\tSinfo id: %ld\n", sinfo->si_id);
259 if (sinfo->si_magic != SI_MAGIC)
260 fprintf(f, "\tSinfo magic: 0x%lX\n", sinfo->si_magic);
261
262 if (sinfo->si_magic != SI_MAGIC ||
263 (sinfo_chksum(scgp, (u_long *)sibuf) !=
264 ((u_long *)sibuf)[scgp->cap->c_bsize/sizeof (u_long) - 1])) {
265 fprintf(f, "\tDisk seems not to be formatted with sformat (release >= 3.0) before.\n");
266 return;
267 }
268 fprintf(f, "\tNumber of reformats: %ld\n", sinfo->si_reformats);
269
270 print_stamp(f, "\tFirst", &sinfo->si_first);
271 if (sinfo->si_reformats > 0)
272 print_stamp(f, "\tLast ", &sinfo->si_last);
273 fprintf(f, "\n");
274 }
275
276 EXPORT BOOL
read_sinfo(scgp,dp,isformat)277 read_sinfo(scgp, dp, isformat)
278 SCSI *scgp;
279 struct disk *dp;
280 BOOL isformat;
281 {
282 int overbose;
283 long spt;
284 long aspz;
285 long tpz;
286 BOOL ret = TRUE;
287
288 overbose = scgp->verbose;
289 scgp->silent++;
290 if (read_capacity(scgp) < 0) {
291 scgp->silent--;
292 scgp->verbose = overbose;
293 return (FALSE);
294 }
295 if (scgp->cap->c_bsize > sizeof (sibuf))
296 comerrno(EX_BAD, "PANIC Sectorsize.\n");
297
298 sinfo_geom(scgp, dp, &spt, &aspz, &tpz);
299
300 fillbytes((caddr_t)sibuf, sizeof (sibuf), '\0');
301 if (read_scsi(scgp, (caddr_t)sibuf, scgp->cap->c_baddr, 1) < 0 &&
302 read_scsi(scgp, (caddr_t)sibuf, scgp->cap->c_baddr - (spt - aspz/tpz), 1) < 0) {
303 errmsgno(EX_BAD, "Cannot read sformat info.\n");
304 scgp->silent--;
305 scgp->verbose = overbose;
306 return (FALSE);
307 }
308 scgp->silent--;
309 scgp->verbose = overbose;
310
311 if (sinfo_chksum(scgp, (u_long *)sibuf) !=
312 ((u_long *)sibuf)[scgp->cap->c_bsize/sizeof (u_long) - 1]) {
313 errmsgno(EX_BAD, "Sformat info not initialized or damaged.\n");
314 ret = FALSE;
315 }
316 if (isformat) {
317 if (((struct sinfo *)sibuf)->si_magic != SI_MAGIC ||
318 ((struct sinfo *)sibuf)->si_release < SI_RELEASE) {
319 /*
320 * Need to upgrade sinfo
321 */
322 fill_sinfo(scgp, (struct sinfo *)sibuf);
323 } else {
324 /*
325 * Need to mark this format action
326 */
327 ((struct sinfo *)sibuf)->si_reformats++;
328 fill_stamp(&((struct sinfo *)sibuf)->si_last);
329 ((u_long *)sibuf)[scgp->cap->c_bsize/sizeof (u_long) - 1] =
330 sinfo_chksum(scgp, (u_long *)sibuf);
331 }
332 }
333 return (ret);
334 }
335
336 EXPORT BOOL
write_sinfo(scgp,dp)337 write_sinfo(scgp, dp)
338 SCSI *scgp;
339 struct disk *dp;
340 {
341 int overbose;
342 long spt;
343 long aspz;
344 long tpz;
345
346 overbose = scgp->verbose;
347 scgp->silent++;
348 if (read_capacity(scgp) < 0) {
349 scgp->silent--;
350 scgp->verbose = overbose;
351 return (FALSE);
352 }
353 if (scgp->cap->c_bsize > sizeof (sibuf))
354 comerrno(EX_BAD, "PANIC Sectorsize.\n");
355
356 sinfo_geom(scgp, dp, &spt, &aspz, &tpz);
357
358 if (write_scsi(scgp, (caddr_t)sibuf, scgp->cap->c_baddr, 1) < 0) {
359 errmsgno(EX_BAD, "Cannot write sformat info.\n");
360 scgp->silent--;
361 scgp->verbose = overbose;
362 return (FALSE);
363 }
364 if (write_scsi(scgp, (caddr_t)sibuf, scgp->cap->c_baddr - (spt - aspz/tpz), 1) < 0) {
365 errmsgno(EX_BAD, "Cannot write backup sformat info.\n");
366 scgp->silent--;
367 scgp->verbose = overbose;
368 return (FALSE);
369 }
370 scgp->silent--;
371 scgp->verbose = overbose;
372 return (TRUE);
373 }
374
375