OSDN Git Service

tests: avoid spurious failure due to extra space in diagnostic
[android-x86/external-parted.git] / libparted / labels / vtoc.c
1 #include <config.h>
2 #include <parted/vtoc.h>
3
4 #ifdef DEBUG_DASD
5 #define PDEBUG fprintf(stderr, "%s:%d:%s\n", \
6                        __FILE__,                              \
7                        __LINE__,                              \
8                        __PRETTY_FUNCTION__);
9 #else
10 #define PDEBUG
11 #endif
12
13 #include <parted/parted.h>
14
15 #include <libintl.h>
16 #if ENABLE_NLS
17 #  define _(String) dgettext (PACKAGE, String)
18 #else
19 #  define _(String) (String)
20 #endif /* ENABLE_NLS */
21
22 static const unsigned char EBCtoASC[256] =
23 {
24 /* 0x00  NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
25         0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
26 /* 0x08  -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
27         0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
28 /* 0x10  DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
29                                 -ENP  ->LF             */
30         0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
31 /* 0x18  CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
32                                                   -IUS */
33         0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
34 /* 0x20  -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
35                                 -INP                   */
36         0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
37 /* 0x28  -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
38                      -SW                               */
39         0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
40 /* 0x30 ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
41         0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
42 /* 0x38 -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
43         0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
44 /* 0x40   SP   RSP           ä              ----       */
45         0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
46 /* 0x48                      .     <     (     +     | */
47         0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
48 /* 0x50    &                                      ---- */
49         0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
50 /* 0x58          ß     !     $     *     )     ;       */
51         0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
52 /* 0x60    -     /  ----     Ä  ----  ----  ----       */
53         0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
54 /* 0x68             ----     ,     %     _     >     ? */
55         0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
56 /* 0x70  ---        ----  ----  ----  ----  ----  ---- */
57         0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
58 /* 0x78    *     `     :     #     @     '     =     " */
59         0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
60 /* 0x80    *     a     b     c     d     e     f     g */
61         0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
62 /* 0x88    h     i              ----  ----  ----       */
63         0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
64 /* 0x90    °     j     k     l     m     n     o     p */
65         0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
66 /* 0x98    q     r                    ----        ---- */
67         0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
68 /* 0xA0          ~     s     t     u     v     w     x */
69         0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
70 /* 0xA8    y     z              ----  ----  ----  ---- */
71         0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
72 /* 0xB0    ^                    ----     §  ----       */
73         0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
74 /* 0xB8       ----     [     ]  ----  ----  ----  ---- */
75         0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
76 /* 0xC0    {     A     B     C     D     E     F     G */
77         0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
78 /* 0xC8    H     I  ----           ö              ---- */
79         0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
80 /* 0xD0    }     J     K     L     M     N     O     P */
81         0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
82 /* 0xD8    Q     R  ----           ü                   */
83         0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
84 /* 0xE0    \           S     T     U     V     W     X */
85         0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
86 /* 0xE8    Y     Z        ----     Ö  ----  ----  ---- */
87         0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
88 /* 0xF0    0     1     2     3     4     5     6     7 */
89         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
90 /* 0xF8    8     9  ----  ----     Ü  ----  ----  ---- */
91         0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
92 };
93
94 static const unsigned char ASCtoEBC[256] =
95 {
96     /*00  NL    SH    SX    EX    ET    NQ    AK    BL */
97         0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
98     /*08  BS    HT    LF    VT    FF    CR    SO    SI */
99         0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
100     /*10  DL    D1    D2    D3    D4    NK    SN    EB */
101         0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26,
102     /*18  CN    EM    SB    EC    FS    GS    RS    US */
103         0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
104     /*20  SP     !     "     #     $     %     &     ' */
105         0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
106     /*28   (     )     *     +     ,     -    .      / */
107         0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
108     /*30   0     1     2     3     4     5     6     7 */
109         0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
110     /*38   8     9     :     ;     <     =     >     ? */
111         0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
112     /*40   @     A     B     C     D     E     F     G */
113         0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
114     /*48   H     I     J     K     L     M     N     O */
115         0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
116     /*50   P     Q     R     S     T     U     V     W */
117         0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
118     /*58   X     Y     Z     [     \     ]     ^     _ */
119         0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
120     /*60   `     a     b     c     d     e     f     g */
121         0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
122     /*68   h     i     j     k     l     m     n     o */
123         0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
124     /*70   p     q     r     s     t     u     v     w */
125         0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
126     /*78   x     y     z     {     |     }     ~    DL */
127         0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
128         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
129         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
130         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
131         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
132         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
133         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
134         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
135         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
136         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
137         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
138         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
139         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
140         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
141         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
142         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
143         0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
144 };
145
146 enum failure {
147         unable_to_open,
148         unable_to_seek,
149         unable_to_write,
150         unable_to_read
151 };
152
153 static char buffer[85];
154
155 static void
156 vtoc_error (enum failure why, char *s1, char *s2)
157 {
158         PDEBUG
159         char error[8192];
160
161         switch (why) {
162                 case unable_to_open:
163                         sprintf(error, "VTOC: %s -- %s\n%s\n",
164                                 _("opening of device failed"), s1, s2);
165                         break;
166                 case unable_to_seek:
167                         sprintf(error, "VTOC: %s -- %s\n%s\n",
168                                 _("seeking on device failed"), s1, s2);
169                         break;
170                 case unable_to_write:
171                         sprintf(error, "VTOC: %s -- %s\n%s\n",
172                                 _("writing to device failed"), s1, s2);
173                         break;
174                 case unable_to_read:
175                         sprintf(error, "VTOC: %s -- %s\n%s\n",
176                                 _("reading from device failed"), s1, s2);
177                         break;
178                 default:
179                         sprintf(error, "VTOC: %s\n", _("Fatal error"));
180         }
181
182         ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, error);
183 }
184
185 char *
186 vtoc_ebcdic_enc (char source[LINE_LENGTH],
187                  char target[LINE_LENGTH],
188                  int l)
189 {
190         PDEBUG
191         int i;
192
193         for (i = 0; i < l; i++)
194                 target[i]=ASCtoEBC[(unsigned char)(source[i])];
195
196         return target;
197 }
198
199 char *
200 vtoc_ebcdic_dec (char source[LINE_LENGTH],
201                  char target[LINE_LENGTH],
202                  int l)
203 {
204         PDEBUG
205         int i;
206
207         for (i = 0; i < l; i++)
208                 target[i]=EBCtoASC[(unsigned char)(source[i])];
209
210         return target;
211 }
212
213 void
214 vtoc_set_extent (extent_t *ext, u_int8_t typeind, u_int8_t seqno,
215                  cchh_t *lower, cchh_t *upper)
216 {
217         PDEBUG
218         ext->typeind = typeind;
219         ext->seqno   = seqno;
220         memcpy(&ext->llimit,lower,sizeof(cchh_t));
221         memcpy(&ext->ulimit,upper,sizeof(cchh_t));
222 }
223
224 void
225 vtoc_set_cchh (cchh_t *addr, u_int16_t cc, u_int16_t hh)
226 {
227         PDEBUG
228         addr->cc = cc;
229         addr->hh = hh;
230 }
231
232 static void
233 vtoc_set_ttr (ttr_t *addr, u_int16_t tt, u_int8_t r)
234 {
235         PDEBUG
236         addr->tt = tt;
237         addr->r = r;
238 }
239
240 void
241 vtoc_set_cchhb (cchhb_t *addr, u_int16_t cc, u_int16_t hh, u_int8_t b)
242 {
243         PDEBUG
244         addr->cc = cc;
245         addr->hh = hh;
246         addr->b = b;
247 }
248
249 void
250 vtoc_set_date (labeldate_t * d, u_int8_t year, u_int16_t day)
251 {
252         PDEBUG
253         d->year = year;
254         d->day = day;
255 }
256
257 /*
258  * initializes the volume label with EBCDIC spaces
259  */
260 void
261 vtoc_volume_label_init (volume_label_t *vlabel)
262 {
263         PDEBUG
264         sprintf(buffer, "%84s", " ");
265         vtoc_ebcdic_enc(buffer, buffer, 84);
266         strncpy(vlabel->volkey, buffer, 84);
267 }
268
269 /*
270  * reads the volume label from dasd
271  */
272 int
273 vtoc_read_volume_label (int f, unsigned long vlabel_start,
274                         volume_label_t *vlabel)
275 {
276         PDEBUG
277         int rc;
278
279         if (lseek(f, vlabel_start, SEEK_SET) == -1) {
280                 vtoc_error(unable_to_seek, "vtoc_read_volume_label",
281                            _("Could not read volume label."));
282                 return 1;
283         }
284
285         rc = read(f, vlabel, sizeof(volume_label_t));
286         if (rc != sizeof(volume_label_t)) {
287                 vtoc_error(unable_to_read, "vtoc_read_volume_label",
288                            _("Could not read volume label."));
289                 return 1;
290         }
291
292         return 0;
293 }
294
295 /*
296  * writes the volume label to dasd
297  */
298 int
299 vtoc_write_volume_label (int f, unsigned long vlabel_start,
300                          volume_label_t *vlabel)
301 {
302         PDEBUG
303         int rc;
304
305         if (lseek(f, vlabel_start, SEEK_SET) == -1)
306                 vtoc_error(unable_to_seek, "vtoc_write_volume_label",
307                            _("Could not write volume label."));
308
309         rc = write(f, vlabel, sizeof(volume_label_t));
310         if (rc != sizeof(volume_label_t))
311                 vtoc_error(unable_to_write, "vtoc_write_volume_label",
312                            _("Could not write volume label."));
313
314         return 0;
315 }
316
317 /*
318  * takes a string as input, converts it to uppercase, translates
319  * it to EBCDIC and fills it up with spaces before it copies it
320  * as volume serial to the volume label
321  */
322 void
323 vtoc_volume_label_set_volser (volume_label_t *vlabel, char *volser)
324 {
325         PDEBUG
326         int j, i = strlen(volser);
327         char s[VOLSER_LENGTH + 1];
328
329         strcpy(s, "      ");
330         vtoc_ebcdic_enc(s, s, VOLSER_LENGTH);
331         strncpy(vlabel->volid, s, VOLSER_LENGTH);
332
333         if (i > VOLSER_LENGTH)
334                 i = VOLSER_LENGTH;
335
336         strncpy(s, volser, i);
337         for (j=0; j<i; j++)
338                 s[j] = toupper(s[j]);
339
340         s[VOLSER_LENGTH] = 0x00;
341         vtoc_ebcdic_enc(s, s, i);
342         strncpy(vlabel->volid, s, i);
343
344         return;
345 }
346
347 /*
348  * returns the volume serial number right after it is translated
349  * to ASCII
350  */
351 char *
352 vtoc_volume_label_get_volser (volume_label_t *vlabel, char *volser)
353 {
354         PDEBUG
355         vtoc_ebcdic_dec(vlabel->volid, volser, VOLSER_LENGTH);
356
357         return volser;
358 }
359
360 /*
361  * sets the volume label key right after
362  * it has been translated to EBCDIC
363  */
364 void
365 vtoc_volume_label_set_key (volume_label_t *vlabel, char *key)
366 {
367         PDEBUG
368         char s[4];
369
370         vtoc_ebcdic_enc(key, s, 4);
371         strncpy(vlabel->volkey, s, 4);
372
373         return;
374 }
375
376 /*
377  * sets the volume label identifier right
378  * after it has been translated to EBCDIC
379  */
380 void
381 vtoc_volume_label_set_label (volume_label_t *vlabel, char *lbl)
382 {
383         PDEBUG
384         char s[4];
385
386         vtoc_ebcdic_enc(lbl, s, 4);
387         strncpy(vlabel->vollbl, s, 4);
388
389         return;
390 }
391
392 /*
393  * returns the volume label key = the label identifier
394  * right after it has been translated to ASCII
395  */
396 char *
397 vtoc_volume_label_get_label (volume_label_t *vlabel, char *lbl)
398 {
399         PDEBUG
400         vtoc_ebcdic_dec(vlabel->vollbl, lbl, 4);
401
402         return lbl;
403 }
404
405 /*
406  * reads either a format4 label or a format1 label
407  * from the specified position
408  */
409 void
410 vtoc_read_label (int f, unsigned long position, format1_label_t *f1,
411                  format4_label_t *f4, format5_label_t *f5, format7_label_t *f7)
412 {
413         PDEBUG
414         int t;
415
416         if (lseek(f, position, SEEK_SET) == -1)
417                 vtoc_error(unable_to_seek, "vtoc_read_label",
418                            _("Could not read VTOC labels."));
419
420         if (f1 != NULL) {
421                 t = sizeof(format1_label_t);
422                 if (read(f, f1, t) != t)
423                         vtoc_error(unable_to_read, "vtoc_read_label",
424                                    _("Could not read VTOC FMT1 DSCB."));
425         }
426
427         if (f4 != NULL) {
428                 t = sizeof(format4_label_t);
429                 if (read(f, f4, t) != t)
430                         vtoc_error(unable_to_read, "vtoc_read_label",
431                                    _("Could not read VTOC FMT4 DSCB."));
432         }
433
434         if (f5 != NULL) {
435                 t = sizeof(format5_label_t);
436                 if (read(f, f5, t) != t)
437                         vtoc_error(unable_to_read, "vtoc_read_label",
438                                    _("Could not read VTOC FMT5 DSCB."));
439         }
440
441         if (f7 != NULL) {
442                 t = sizeof(format7_label_t);
443                 if (read(f, f7, t) != t)
444                         vtoc_error(unable_to_read, "vtoc_read_label",
445                                    _("Could not read VTOC FMT7 DSCB."));
446         }
447 }
448
449 /*
450  * writes either a FMT1, FMT4 or FMT5 label
451  * to the specified position
452  */
453 void
454 vtoc_write_label (int f, unsigned long position, format1_label_t *f1,
455                   format4_label_t *f4, format5_label_t *f5, format7_label_t *f7)
456 {
457         PDEBUG
458         int t;
459
460         if (lseek(f, position, SEEK_SET) == -1)
461                 vtoc_error(unable_to_seek, "vtoc_write_label",
462                            _("Could not write VTOC labels."));
463
464         if (f1 != NULL) {
465                 t = sizeof(format1_label_t);
466                 if (write(f, f1, t) != t)
467                         vtoc_error(unable_to_write, "vtoc_write_label",
468                                    _("Could not write VTOC FMT1 DSCB."));
469         }
470
471         if (f4 != NULL) {
472                 t = sizeof(format4_label_t);
473                 if (write(f, f4, t) != t)
474                         vtoc_error(unable_to_write, "vtoc_write_label",
475                                    _("Could not write VTOC FMT4 DSCB."));
476         }
477
478         if (f5 != NULL) {
479                 t = sizeof(format5_label_t);
480                 if (write(f, f5, t) != t)
481                         vtoc_error(unable_to_write, "vtoc_write_label",
482                                    _("Could not write VTOC FMT5 DSCB."));
483         }
484
485         if (f7 != NULL) {
486                 t = sizeof(format7_label_t);
487                 if (write(f, f7, t) != t)
488                         vtoc_error(unable_to_write, "vtoc_write_label",
489                                    _("Could not write VTOC FMT7 DSCB."));
490         }
491 }
492
493 /*
494  * initializes a format4 label
495  */
496 void
497 vtoc_init_format4_label (format4_label_t *f4, unsigned int usable_partitions,
498                          unsigned int cylinders, unsigned int tracks,
499                          unsigned int blocks, unsigned int blksize,
500                          u_int16_t dev_type)
501 {
502         PDEBUG
503         int i;
504
505         cchh_t lower = {VTOC_START_CC, VTOC_START_HH};
506         cchh_t upper = {VTOC_START_CC, VTOC_START_HH};
507
508         for (i=0; i<44; i++) f4->DS4KEYCD[i] = 0x04;
509         f4->DS4IDFMT = 0xf4;
510
511         vtoc_set_cchhb(&f4->DS4HPCHR, 0x0000, 0x0000, 0x00);
512         f4->DS4DSREC = blocks - 2;
513         /* free space starts right behind VTOC
514            vtoc_set_cchh(&f4->DS4HCCHH, VTOC_START_CC, VTOC_START_HH + 1);*/
515         vtoc_set_cchh(&f4->DS4HCCHH, 0x0000, 0x0000);
516         f4->DS4NOATK = 0x0000;
517         f4->DS4VTOCI = 0x00;
518         f4->DS4NOEXT = 0x01;
519         f4->DS4SMSFG = 0x00;
520         f4->DS4DEVAC = 0x00;
521
522         /* -- begin f4->DS4DEVCT -- */
523         f4->DS4DEVCT.DS4DSCYL = cylinders;
524         f4->DS4DEVCT.DS4DSTRK = tracks;
525
526         switch (dev_type) {
527                 case DASD_3380_TYPE:
528                         f4->DS4DEVCT.DS4DEVTK = DASD_3380_VALUE;
529                         break;
530                 case DASD_3390_TYPE:
531                         f4->DS4DEVCT.DS4DEVTK = DASD_3390_VALUE;
532                         break;
533                 case DASD_9345_TYPE:
534                         f4->DS4DEVCT.DS4DEVTK = DASD_9345_VALUE;
535                         break;
536                 default:
537                         f4->DS4DEVCT.DS4DEVTK = blocks * blksize;;
538         }
539
540         f4->DS4DEVCT.DS4DEVI  = 0x00;
541         f4->DS4DEVCT.DS4DEVL  = 0x00;
542         f4->DS4DEVCT.DS4DEVK  = 0x00;
543         f4->DS4DEVCT.DS4DEVFG = 0x30;
544         f4->DS4DEVCT.DS4DEVTL = 0x0000;
545         f4->DS4DEVCT.DS4DEVDT = blocks;
546         f4->DS4DEVCT.DS4DEVDB = 0x00;
547         /* -- end f4->DS4DEVCT -- */
548
549         bzero(f4->DS4AMTIM, sizeof(f4->DS4AMTIM));
550         bzero(f4->DS4AMCAT, sizeof(f4->DS4AMCAT));
551         bzero(f4->DS4R2TIM, sizeof(f4->DS4R2TIM));
552         bzero(f4->res1, sizeof(f4->res1));
553         bzero(f4->DS4F6PTR, sizeof(f4->DS4F6PTR));
554
555         /* -- begin f4lbl->DS4VTOCE -- */
556         vtoc_set_extent(&f4->DS4VTOCE, 0x01, 0x00, &lower, &upper);
557         /* -- end f4lbl->DS4VTOCE -- */
558
559         bzero(f4->res2, sizeof(f4->res2));
560         f4->DS4EFLVL = 0x00;
561         bzero(&f4->DS4EFPTR, sizeof(f4->DS4EFPTR));
562         bzero(f4->res3, sizeof(f4->res3));
563 }
564
565 /*
566  * initializes a format5 label
567  */
568 void
569 vtoc_init_format5_label (format5_label_t *f5)
570 {
571         PDEBUG
572         int i;
573
574         bzero(f5, sizeof(format5_label_t));
575         for (i=0; i<4; i++)
576                 f5->DS5KEYID[i] = 0x05;
577         f5->DS5FMTID = 0xf5;
578 }
579
580 /*
581  * initializes a format7 label
582  */
583 void
584 vtoc_init_format7_label (format7_label_t *f7)
585 {
586         PDEBUG
587         int i;
588
589         bzero(f7, sizeof(format7_label_t));
590         for (i=0; i<4; i++)
591                 f7->DS7KEYID[i] = 0x07;
592         f7->DS7FMTID = 0xf7;
593 }
594
595 /*
596  * initializes a format1 label
597  */
598 void
599 vtoc_init_format1_label (char *volid, unsigned int blksize,
600                          extent_t *part_extent, format1_label_t *f1)
601 {
602         PDEBUG
603         struct tm * creatime;
604         time_t t;
605         char str[80];
606
607         /* get actual date */
608         t = time(NULL);
609         creatime = gmtime(&t);
610
611         bzero(f1->DS1DSNAM, sizeof(f1->DS1DSNAM));
612         sprintf(str, "PART    .NEW                                ");
613         vtoc_ebcdic_enc(str, str, 44);
614         strncpy(f1->DS1DSNAM, str, 44);
615         f1->DS1FMTID = 0xf1;
616         strncpy(f1->DS1DSSN, "      ", 6);
617         f1->DS1VOLSQ = 0x0001;
618
619         vtoc_set_date(&f1->DS1CREDT, (u_int8_t) creatime->tm_year,
620                                   (u_int16_t) creatime->tm_yday);
621         /* expires never - 99 365 */
622         vtoc_set_date(&f1->DS1EXPDT, 0x63, 0x016D);
623         f1->DS1NOEPV = 0x01;
624         f1->DS1NOBDB = 0x00;
625         f1->DS1FLAG1 = 0x00;
626         vtoc_ebcdic_enc("IBM LINUX    ", str, 13);
627         strncpy(f1->DS1SYSCD, str, 13);
628         vtoc_set_date(&f1->DS1REFD, (u_int8_t) creatime->tm_year,
629                                   (u_int16_t) creatime->tm_yday);
630         f1->DS1SMSFG = 0x00;
631         f1->DS1SCXTF = 0x00;
632         f1->DS1SCXTV = 0x0000;
633         f1->DS1DSRG1 = 0x00;
634         f1->DS1DSRG2 = 0x00;
635         f1->DS1RECFM = 0x88;
636         f1->DS1OPTCD = 0x00;
637         f1->DS1BLKL  = blksize;
638         f1->DS1LRECL = blksize;
639         f1->DS1KEYL  = 0x00;
640         f1->DS1RKP   = 0x0000;
641         f1->DS1DSIND = 0x80; /* last volume for this dataset */
642         f1->DS1SCAL1 = 0x80;
643         bzero(&f1->DS1SCAL3, sizeof(f1->DS1SCAL3));
644         vtoc_set_ttr(&f1->DS1LSTAR, 0x0000, 0x00);
645         f1->DS1TRBAL = 0x00;
646         bzero(&f1->res1, sizeof(f1->res1));
647         memcpy(&f1->DS1EXT1, part_extent, sizeof(extent_t));
648         bzero(&f1->DS1EXT2, sizeof(extent_t));
649         bzero(&f1->DS1EXT3, sizeof(extent_t));
650         vtoc_set_cchhb(&f1->DS1PTRDS, 0x0000, 0x0000, 0x00);
651 }
652
653 /*
654  * do some updates to the VTOC format4 label
655  */
656 void
657 vtoc_update_format4_label (format4_label_t *f4, cchhb_t *highest_f1,
658                            u_int16_t unused_update)
659 {
660         PDEBUG
661         /* update highest address of a format 1 label */
662         memcpy(&f4->DS4HPCHR, highest_f1, sizeof(cchhb_t));
663
664         /* update unused DSCB count */
665         f4->DS4DSREC = unused_update;
666 }
667
668 /*
669  * reorganizes all extents within a FMT5 label
670  */
671 static void
672 vtoc_reorganize_FMT5_extents (format5_label_t *f5)
673 {
674         PDEBUG
675         ds5ext_t *ext, *last, tmp;
676         int i, j;
677
678         for (i=0; i<26; i++) {
679                 if (i==0)
680                         last = &f5->DS5AVEXT;
681                 else if ((i > 0) && (i < 8))
682                         last = &f5->DS5EXTAV[i-1];
683                 else
684                         last = &f5->DS5MAVET[i-8];
685
686                 for (j=i; j<26; j++) {
687                         if (j==0)
688                                 ext = &f5->DS5AVEXT;
689                         else if ((j > 0) && (j < 8))
690                                 ext = &f5->DS5EXTAV[j-1];
691                         else
692                                 ext = &f5->DS5MAVET[j-8];
693
694                         if (((ext->t > 0) && (last->t == 0)) ||
695                             ((ext->t > 0) && (ext->t < last->t)))
696                         {
697                                 tmp.t  = last->t;
698                                 tmp.fc = last->fc;
699                                 tmp.ft = last->ft;
700                                 last->t  = ext->t;
701                                 last->fc = ext->fc;
702                                 last->ft = ext->ft;
703                                 ext->t  = tmp.t;
704                                 ext->fc = tmp.fc;
705                                 ext->ft = tmp.ft;
706                         }
707                 }
708         }
709 }
710
711 /*
712  * add a free space extent description to the VTOC FMT5 DSCB
713  */
714 void
715 vtoc_update_format5_label_add (format5_label_t *f5, int verbose, int cyl,
716                                int trk, u_int16_t a, u_int16_t b, u_int8_t c)
717 {
718         PDEBUG
719         ds5ext_t *ext = NULL, *tmp = NULL;
720         int i;
721
722         for (i=0; i<26; i++) {
723                 if (i==0)
724                         ext = &f5->DS5AVEXT;
725                 else if ((i > 0) && (i < 8))
726                         ext = &f5->DS5EXTAV[i-1];
727                 else
728                         ext = &f5->DS5MAVET[i-8];
729
730                 if (((a < ext->t) && (a + b*trk + c > ext->t)) ||
731                     ((a > ext->t) && (ext->t + ext->fc*trk + ext->ft > a)))
732                 {
733                         puts ("BUG: overlapping free space extents "
734                               "in FMT5 DSCB!\nexiting...");
735                         exit(1);
736                 }
737
738                 if ((ext->t + ext->fc + ext->ft) == 0x0000) {
739                         ext->t  = a;
740                         ext->fc = b;
741                         ext->ft = c;
742                         tmp = ext;
743                         if (verbose)
744                                 puts ("FMT5 add extent: add new extent");
745                         break;
746                 }
747         }
748
749         if (tmp == NULL) {
750                 /* BUG: no free extent found */
751                 puts ("BUG: no free FMT5 DSCB extent found!\nexiting...");
752                 exit(1);
753         }
754
755         for (i=0; i<26; i++) {
756                 if (i==0)
757                         ext = &f5->DS5AVEXT;
758                 else if ((i > 0) && (i < 8))
759                         ext = &f5->DS5EXTAV[i-1];
760                 else
761                         ext = &f5->DS5MAVET[i-8];
762
763                 if ((ext->t + ext->fc + ext->ft) == 0x0000)
764                         continue;
765
766                 if ((ext->t + ext->fc*trk + ext->ft) == tmp->t) {
767                         /* this extent precedes the new one */
768                         ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
769                         ext->ft = (tmp->ft + ext->ft) % trk;
770                         bzero(tmp, sizeof(ds5ext_t));
771                         tmp = ext;
772
773                         if (verbose)
774                                 puts ("FMT5 add extent: "
775                                       "merge with predecessor");
776
777                         i = -1;
778                         continue;
779                 }
780
781                 if ((tmp->t + tmp->fc*trk + tmp->ft) == ext->t) {
782                         /* this extent succeeds the new one */
783                         ext->t = tmp->t;
784                         ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
785                         ext->ft = (tmp->ft + ext->ft) % trk;
786                         bzero(tmp, sizeof(ds5ext_t));
787                         tmp = ext;
788
789                         if (verbose)
790                                 puts ("FMT5 add extent: "
791                                       "merge with successor");
792
793                         i = -1;
794                         continue;
795                 }
796         }
797 }
798
799 /*
800  * remove a free space extent description from the VTOC FMT5 DSCB
801  */
802 void
803 vtoc_update_format5_label_del (format5_label_t *f5, int verbose, int cyl,
804                                int trk, u_int16_t a, u_int16_t b, u_int8_t c)
805 {
806         PDEBUG
807         ds5ext_t *ext;
808         int i, counter=0;
809
810         for (i=0; i<26; i++) {
811                 if (i==0)
812                         ext = &f5->DS5AVEXT;
813                 else if ((i > 0) && (i < 8))
814                         ext = &f5->DS5EXTAV[i-1];
815                 else
816                         ext = &f5->DS5MAVET[i-8];
817
818                 if ((a == ext->t) && (b == ext->fc) && (c == ext->ft)) {
819                         /* fills up whole free space gap */
820                         bzero(ext, sizeof(ds5ext_t));
821
822                         if (verbose)
823                                 puts ("FMT5 del extent: fills whole gap");
824
825                         counter++;
826                         break;
827                 }
828
829                 if ((a == ext->t) && ((b < ext->fc) || (c < ext->ft))) {
830                         /* left-bounded in free space gap */
831                         ext->t = ext->t + b*trk + c;
832
833                         if (c > ext->ft) {
834                                 ext->fc -= (b + 1);
835                                 ext->ft -= (c - trk);
836                         } else {
837                                 ext->fc -= b;
838                                 ext->ft -= c;
839                         }
840
841                         if (verbose)
842                                 puts ("FMT5 del extent: left bounded");
843
844                         counter++;
845                         break;
846                 }
847
848                 if ((ext->t < a)
849                     && ((ext->t + ext->fc*trk + ext->ft) == (a + b*trk + c)))
850                 {
851                         /* right-bounded in free space gap */
852                         if (c > ext->ft) {
853                                 ext->fc -= (b + 1);
854                                 ext->ft -= (c - trk);
855                         } else {
856                                 ext->fc -= b;
857                                 ext->ft -= c;
858                         }
859
860                         if (verbose)
861                                 puts ("FMT5 del extent: right bounded");
862
863                         counter++;
864                         break;
865                 }
866
867                 if ((a > ext->t)
868                         && ((ext->t + ext->fc*trk + ext->ft) > (a + b*trk + c)))
869                 {
870                         /* partition devides free space into 2 pieces */
871                         u_int16_t x = a + b*trk + c;
872                         u_int16_t w,y;
873                         u_int8_t z;
874
875                         w = (ext->t + ext->fc*trk + ext->ft) - (a + b*trk + c);
876                         y = w / trk;
877                         z = w % trk;
878
879                         ext->fc = (a - ext->t) / trk;
880                         ext->ft = (a - ext->t) % trk;
881
882                         vtoc_update_format5_label_add(f5, verbose,
883                                                       cyl, trk, x, y, z);
884
885                         if (verbose)
886                                 puts ("FMT5 del extent: 2 pieces");
887
888                         counter++;
889                         break;
890                 }
891
892                 if ((a < ext->t) && (a + b*trk + c > ext->t)
893                     && (a + b*trk + c < ext->t + ext->fc*trk + ext->ft))
894                 {
895                         puts ("BUG: corresponding free space extent "
896                               "doesn't match free space currently shown "
897                               "in FMT5 DSCB!\nexiting...");
898                         exit(1);
899                 }
900
901                 if ((a > ext->t) && (a < ext->t + ext->fc*trk + ext->ft)
902                     && (a + b*trk + c > ext->t + ext->fc*trk + ext->ft))
903                 {
904                         puts ("BUG: specified free space extent for "
905                               "deleting doesn't match free space "
906                               "currently shown in FMT5 DSCB!\n"
907                               "exiting...");
908                         exit(1);
909                 }
910         }
911
912         if (counter > 0)
913                 return;
914
915         puts ("BUG: specified free space extent for "
916               "deleting not found in FMT5 DSCB!\n"
917               "exiting...");
918         exit(1);
919 }
920
921 /*
922  * reorganizes all extents within a FMT7 label
923  */
924 static void
925 vtoc_reorganize_FMT7_extents (format7_label_t *f7)
926 {
927         PDEBUG
928         ds7ext_t *ext, *last, tmp;
929         int i, j;
930
931         for (i=0; i<16; i++) {
932                 if (i<5)
933                         last = &f7->DS7EXTNT[i];
934                 else
935                         last = &f7->DS7ADEXT[i-5];
936
937                 for (j=i; j<16; j++) {
938                         if (j<5)
939                                 ext = &f7->DS7EXTNT[j];
940                         else
941                                 ext = &f7->DS7ADEXT[j-5];
942
943                         if (((ext->a > 0) && (last->a == 0))
944                             || ((ext->a > 0) && (ext->a < last->a)))
945                         {
946                                 tmp.a = last->a;
947                                 tmp.b = last->b;
948                                 last->a = ext->a;
949                                 last->b = ext->b;
950                                 ext->a = tmp.a;
951                                 ext->b = tmp.b;
952                         }
953                 }
954         }
955 }
956
957 /*
958  * add a free space extent description to the VTOC FMT7 DSCB
959  */
960 void
961 vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
962                                u_int32_t a, u_int32_t b)
963 {
964         PDEBUG
965         ds7ext_t *ext = NULL, *tmp = NULL;
966         int i;
967
968         for (i=0; i<16; i++) {
969                 if (i<5)
970                         ext = &f7->DS7EXTNT[i];
971                 else
972                         ext = &f7->DS7ADEXT[i-5];
973
974                 if (((a < ext->a) && (b > ext->a) && (b < ext->b))
975                     || ((a > ext->a) && (a < ext->b) && (b > ext->b)))
976                 {
977                         puts ("BUG: overlapping free space extents "
978                               "in FMT7 DSCB!\nexiting...");
979                         exit(1);
980                 }
981
982                 if ((ext->a + ext->b) == 0x00000000) {
983                         ext->a = a;
984                         ext->b = b;
985                         tmp = ext;
986
987                         if (verbose)
988                                 puts ("FMT7 add extent: add new extent");
989
990                         break;
991                 }
992         }
993
994         if (tmp == NULL) {
995                 /* BUG: no free extent found */
996                 puts ("BUG: no free FMT7 DSCB extent found!\nexiting...");
997                 exit(1);
998         }
999
1000         for (i=0; i<16; i++) {
1001                 if (i<5)
1002                         ext = &f7->DS7EXTNT[i];
1003                 else
1004                         ext = &f7->DS7ADEXT[i-5];
1005
1006                 if ((ext->a + ext->b) == 0x00000000)
1007                         continue;
1008
1009                 if ((ext->b + 1) == tmp->a) {
1010                         /* this extent precedes the new one */
1011                         ext->b = tmp->b;
1012                         bzero(tmp, sizeof(ds7ext_t));
1013                         tmp = ext;
1014
1015                         if (verbose)
1016                                 puts ("FMT7 add extent: "
1017                                       "merge with predecessor");
1018
1019                         i = -1;
1020                         continue;
1021                 }
1022
1023                 if (ext->a == (tmp->b + 1)) {
1024                         /* this extent succeeds the new one */
1025                         ext->a = tmp->a;
1026                         bzero(tmp, sizeof(ds7ext_t));
1027                         tmp = ext;
1028
1029                         if (verbose)
1030                                 puts ("FMT7 add extent: merge with successor");
1031
1032                         i = -1;
1033                         continue;
1034                 }
1035         }
1036 }
1037
1038 /*
1039  * remove a free space extent description from the VTOC FMT7 DSCB
1040  */
1041 void
1042 vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
1043                                u_int32_t a, u_int32_t b)
1044 {
1045         PDEBUG
1046         ds7ext_t *ext;
1047         int i, counter=0;
1048
1049         for (i=0; i<16; i++) {
1050                 if (i<5)
1051                         ext = &f7->DS7EXTNT[i];
1052                 else
1053                         ext = &f7->DS7ADEXT[i-5];
1054
1055                 if ((a == ext->a) && (b == ext->b)) {
1056                         /* fills up whole free space gap */
1057                         bzero(ext, sizeof(ds7ext_t));
1058
1059                         if (verbose)
1060                                 puts ("FMT7 del extent: fills whole gap");
1061
1062                         counter++;
1063                         break;
1064                 }
1065
1066                 if ((a == ext->a) && (b < ext->b)) {
1067                         /* left-bounded in free space gap */
1068                         ext->a = b + 1;
1069
1070                         if (verbose)
1071                                 puts ("FMT7 add extent: left-bounded");
1072
1073                         counter++;
1074                         break;
1075                 }
1076
1077                 if ((a > ext->a) && (b == ext->b)) {
1078                         /* right-bounded in free space gap */
1079                         ext->b = a - 1;
1080
1081                         if (verbose)
1082                                 puts ("FMT7 add extent: right-bounded");
1083
1084                         counter++;
1085                         break;
1086                 }
1087
1088                 if ((a > ext->a) && (b < ext->b)) {
1089                         /* partition devides free space into 2 pieces */
1090                         vtoc_update_format7_label_add(f7, verbose, b+1, ext->b);
1091                         ext->b = a - 1;
1092
1093                         if (verbose)
1094                                 puts ("FMT7 add extent: 2 pieces");
1095
1096                         counter++;
1097                         break;
1098                 }
1099
1100                 if (((a < ext->a) && (b > ext->a)) || ((a < ext->b) && (b > ext->b))) {
1101                         puts ("BUG: specified free space extent for deleting "
1102                               "doesn't match free space currently shown in "
1103                               "FMT7 DSCB!\nexiting...");
1104                         printf ("%d %d %d %d\n", a, b, ext->a, ext->b);
1105                         exit(1);
1106                 }
1107         }
1108
1109         if (counter > 0)
1110                 return;
1111
1112         puts ("BUG: specified free space extent for "
1113               "deleting not found in FMT7 DSCB!\n"
1114               "exiting...");
1115         exit(1);
1116 }
1117
1118 void
1119 vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
1120                    format7_label_t *f7, char ch, int verbose,
1121                    u_int32_t start, u_int32_t stop, int cyl, int trk)
1122 {
1123         PDEBUG
1124         if ((cyl * trk) > BIG_DISK_SIZE) {
1125                 if (ch == '+')
1126                         vtoc_update_format7_label_add(f7, verbose, start, stop);
1127                 else if (ch == '-')
1128                         vtoc_update_format7_label_del(f7, verbose, start, stop);
1129                 else
1130                         puts ("BUG: syntax error in vtoc_set_freespace call");
1131
1132                 vtoc_reorganize_FMT7_extents (f7);
1133
1134                 f4->DS4VTOCI = 0xa0;
1135                 f4->DS4EFLVL = 0x07;
1136                 vtoc_set_cchhb(&f4->DS4EFPTR, 0x0000, 0x0001, 0x03);
1137         } else {
1138                 u_int16_t x,y;
1139                 u_int8_t z;
1140
1141                 x = (u_int16_t) start;
1142                 y = (u_int16_t) ((stop - start + 1) / trk);
1143                 z =  (u_int8_t) ((stop - start + 1) % trk);
1144
1145                 if (ch == '+')
1146                         vtoc_update_format5_label_add(f5, verbose, cyl, trk, x, y, z);
1147                 else if (ch == '-')
1148                         vtoc_update_format5_label_del(f5, verbose, cyl, trk, x, y, z);
1149                 else
1150                         puts ("BUG: syntax error in vtoc_set_freespace call");
1151
1152                 vtoc_reorganize_FMT5_extents (f5);
1153         }
1154 }