1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This file contains the code to add new disk_type and partition 29 * definitions to a format data file. 30 */ 31 #include "global.h" 32 33 #include <ctype.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <fcntl.h> 38 #include <errno.h> 39 #include <memory.h> 40 #include <sys/fcntl.h> 41 #include <sys/param.h> 42 #include <time.h> 43 #include <sys/time.h> 44 #include <stdarg.h> 45 46 #include "add_definition.h" 47 #include "misc.h" 48 #include "partition.h" 49 #include "menu_command.h" 50 #include "startup.h" 51 52 extern struct ctlr_type ctlr_types[]; 53 extern int nctypes; 54 55 extern int errno; 56 57 /* Function prototypes */ 58 #ifdef __STDC__ 59 60 static void add_disktype(FILE *fd, struct disk_info *disk_info); 61 static void add_partition(FILE *fd, struct disk_info *, 62 struct partition_info *); 63 static int add_entry(int col, FILE *fd, char *format, ...); 64 65 #else /* __STDC__ */ 66 67 static void add_disktype(); 68 static void add_partition(); 69 static int add_entry(); 70 71 #endif /* __STDC__ */ 72 73 /* 74 * Add new definitions for the current disk/partition to a format data file. 75 */ 76 int 77 add_definition(void) 78 { 79 FILE *fd; 80 char *filename; 81 time_t clock; 82 char *prompt; 83 union { 84 int xfoo; 85 char deflt_str[MAXPATHLEN]; 86 } x; 87 88 /* 89 * There must be a current disk and partition table 90 */ 91 if (cur_disk == NULL) { 92 err_print("No Current Disk.\n"); 93 return (0); 94 } 95 if (cur_dtype == NULL) { 96 err_print("Current disk type is not set.\n"); 97 return (-1); 98 } 99 if (cur_parts == NULL) { 100 err_print("Current partition is not set.\n"); 101 return (-1); 102 } 103 /* 104 * If neither the disk definition nor the partition 105 * information has been changed, there's nothing to save. 106 */ 107 if (cur_dtype->dtype_filename != NULL && 108 cur_parts->pinfo_filename != NULL) { 109 err_print("\ 110 Neither the disk type nor the partitioning has been changed.\n"); 111 return (-1); 112 } 113 /* 114 * If saving the partition, and it's unnamed, the user should name 115 * it first. 116 */ 117 if (cur_parts->pinfo_name == NULL) { 118 assert(cur_parts->pinfo_filename == NULL); 119 err_print("Please name this partition type before saving it\n"); 120 return (-1); 121 } 122 /* 123 * Let the user know what we're doing 124 */ 125 if (cur_dtype->dtype_filename == NULL && 126 cur_parts->pinfo_filename == NULL) { 127 fmt_print("Saving new disk and partition definitions\n"); 128 } else if (cur_dtype->dtype_filename == NULL) { 129 fmt_print("Saving new disk definition\n"); 130 } else { 131 assert(cur_parts->pinfo_filename == NULL); 132 fmt_print("Saving new partition definition\n"); 133 } 134 /* 135 * Ask for the file to which to append the new definitions 136 */ 137 prompt = "Enter file name"; 138 (void) strcpy(x.deflt_str, "./format.dat"); 139 filename = (char *)(uintptr_t)input(FIO_OSTR, prompt, 140 ':', NULL, &x.xfoo, DATA_INPUT); 141 assert(filename != NULL); 142 /* 143 * Open the file in append mode, or create it, if necessary 144 */ 145 if ((fd = fopen(filename, "a")) == NULL) { 146 err_print("Cannot open `%s' - %s\n", filename, 147 strerror(errno)); 148 destroy_data(filename); 149 return (-1); 150 } 151 /* 152 * Write a header for the new definitions 153 */ 154 if ((cur_dtype->dtype_filename == NULL) && 155 (cur_parts->pinfo_filename == NULL)) { 156 (void) fprintf(fd, "#\n# New disk/partition type "); 157 } else if (cur_dtype->dtype_filename == NULL) { 158 (void) fprintf(fd, "#\n# New disk type "); 159 } else { 160 (void) fprintf(fd, "#\n# New partition type "); 161 } 162 (void) time(&clock); 163 (void) fprintf(fd, " saved on %s#\n", ctime(&clock)); 164 /* 165 * Save the new definitions 166 */ 167 if (cur_dtype->dtype_filename == NULL) { 168 add_disktype(fd, cur_disk); 169 } 170 if (cur_parts->pinfo_filename == NULL) { 171 add_partition(fd, cur_disk, cur_parts); 172 } 173 /* 174 * We're finished. Clean up 175 */ 176 (void) fclose(fd); 177 destroy_data(filename); 178 return (0); 179 } 180 181 /* 182 * Add a disk_type definition to the file fd 183 */ 184 static void 185 add_disktype(FILE *fd, struct disk_info *disk_info) 186 { 187 int col; 188 struct disk_type *disk_type; 189 190 disk_type = disk_info->disk_type; 191 192 (void) fprintf(fd, "disk_type = \"%s\" \\\n", 193 disk_type->dtype_asciilabel); 194 col = add_entry(0, fd, " : ctlr = %s", 195 ((disk_info->disk_ctlr)->ctlr_ctype)->ctype_name); 196 197 col = add_entry(col, fd, " : ncyl = %d", disk_type->dtype_ncyl); 198 199 col = add_entry(col, fd, " : acyl = %d", disk_type->dtype_acyl); 200 201 col = add_entry(col, fd, " : pcyl = %d", disk_type->dtype_pcyl); 202 203 col = add_entry(col, fd, " : nhead = %d", disk_type->dtype_nhead); 204 205 if (disk_type->dtype_options & SUP_PHEAD) { 206 col = add_entry(col, fd, " : phead = %d", 207 disk_type->dtype_phead); 208 } 209 210 col = add_entry(col, fd, " : nsect = %d", disk_type->dtype_nsect); 211 212 if (disk_type->dtype_options & SUP_PSECT) { 213 col = add_entry(col, fd, " : psect = %d", 214 disk_type->dtype_psect); 215 } 216 217 if (disk_type->dtype_options & SUP_BPT) { 218 col = add_entry(col, fd, " : bpt = %d", disk_type->dtype_bpt); 219 } 220 221 col = add_entry(col, fd, " : rpm = %d", disk_type->dtype_rpm); 222 223 if (disk_type->dtype_options & SUP_FMTTIME) { 224 col = add_entry(col, fd, " : fmt_time = %d", 225 disk_type->dtype_fmt_time); 226 } 227 228 if (disk_type->dtype_options & SUP_CYLSKEW) { 229 col = add_entry(col, fd, " : cyl_skew = %d", 230 disk_type->dtype_cyl_skew); 231 } 232 233 if (disk_type->dtype_options & SUP_TRKSKEW) { 234 col = add_entry(col, fd, " : trk_skew = %d", 235 disk_type->dtype_trk_skew); 236 } 237 238 if (disk_type->dtype_options & SUP_TRKS_ZONE) { 239 col = add_entry(col, fd, " : trks_zone = %d", 240 disk_type->dtype_trks_zone); 241 } 242 243 if (disk_type->dtype_options & SUP_ATRKS) { 244 col = add_entry(col, fd, " : atrks = %d", 245 disk_type->dtype_atrks); 246 } 247 248 if (disk_type->dtype_options & SUP_ASECT) { 249 col = add_entry(col, fd, " : asect = %d", 250 disk_type->dtype_asect); 251 } 252 253 if (disk_type->dtype_options & SUP_CACHE) { 254 col = add_entry(col, fd, " : cache = %d", 255 disk_type->dtype_cache); 256 } 257 258 if (disk_type->dtype_options & SUP_PREFETCH) { 259 col = add_entry(col, fd, " : prefetch = %d", 260 disk_type->dtype_threshold); 261 } 262 263 if (disk_type->dtype_options & SUP_CACHE_MIN) { 264 col = add_entry(col, fd, " : min_prefetch = %d", 265 disk_type->dtype_prefetch_min); 266 } 267 268 if (disk_type->dtype_options & SUP_CACHE_MAX) { 269 col = add_entry(col, fd, " : max_prefetch = %d", 270 disk_type->dtype_prefetch_max); 271 } 272 273 if (disk_type->dtype_options & SUP_BPS) { 274 col = add_entry(col, fd, " : bps = %d", 275 disk_type->dtype_bps); 276 } 277 278 if (disk_type->dtype_options & SUP_DRTYPE) { 279 col = add_entry(col, fd, " : drive_type = %d", 280 disk_type->dtype_dr_type); 281 } 282 283 /* 284 * Terminate the last line, and print one blank line 285 */ 286 (void) fprintf(fd, col == 0 ? "\n" : "\n\n"); 287 } 288 289 290 291 /* 292 * Once we exceed this length, wrap to a new line 293 */ 294 #define MAX_COLUMNS 50 295 296 /* 297 * Add a partition definition to the file fd 298 */ 299 static void 300 add_partition(FILE *fd, struct disk_info *disk_info, 301 struct partition_info *part) 302 { 303 int col; 304 int i; 305 struct disk_type *disk_type; 306 struct dk_map32 *pp; 307 char *s; 308 309 #if defined(_SUNOS_VTOC_8) 310 struct dk_map2 *pv; 311 312 #elif defined(_SUNOS_VTOC_16) 313 struct dkl_partition *pv; 314 315 #else 316 #error No VTOC format defined. 317 #endif /* defined (_SUNOS_VTOC_8) */ 318 struct dk_map2 *dv; 319 320 disk_type = disk_info->disk_type; 321 322 (void) fprintf(fd, "partition = \"%s\" \\\n", part->pinfo_name); 323 (void) fprintf(fd, "\t : disk = \"%s\" : ctlr = %s \\\n", 324 disk_type->dtype_asciilabel, 325 ((disk_info->disk_ctlr)->ctlr_ctype)->ctype_name); 326 327 /* 328 * Print the specifications for each useful partition 329 */ 330 col = 0; 331 pp = part->pinfo_map; 332 pv = part->vtoc.v_part; 333 dv = default_vtoc_map; 334 for (i = 0; i < NDKMAP; i++, pp++, pv++, dv++) { 335 if (pp->dkl_nblk != 0) { 336 col = add_entry(col, fd, " : %c = ", 337 i + PARTITION_BASE); 338 if (pv->p_tag != dv->p_tag || 339 pv->p_flag != dv->p_flag) { 340 s = find_string(ptag_choices, (int)pv->p_tag); 341 if (s != NULL) { 342 col = add_entry(col, fd, " %s,", s); 343 } 344 s = find_string(pflag_choices, (int)pv->p_flag); 345 if (s != NULL) { 346 col = add_entry(col, fd, " %s,", s); 347 } 348 } 349 col = add_entry(col, fd, " %d, %d", pp->dkl_cylno, 350 pp->dkl_nblk); 351 } 352 } 353 354 /* 355 * Terminate the last line, and print one blank line 356 */ 357 (void) fprintf(fd, col == 0 ? "\n" : "\n\n"); 358 } 359 360 /* 361 * Add an entry to the file fd. col is the current starting column. 362 * Return the resulting new column position. 363 */ 364 /*PRINTFLIKE3*/ 365 static int 366 add_entry(int col, FILE *fd, char *format, ...) 367 { 368 va_list ap; 369 va_start(ap, format); 370 371 if (col > MAX_COLUMNS) { 372 (void) fprintf(fd, " \\\n"); 373 col = 0; 374 } 375 if (col == 0) { 376 col += fprintf(fd, "\t"); 377 } 378 col += vfprintf(fd, format, ap); 379 va_end(ap); 380 381 return (col); 382 } 383