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 static void add_disktype(FILE *fd, struct disk_info *disk_info); 59 static void add_partition(FILE *fd, struct disk_info *, 60 struct partition_info *); 61 static int add_entry(int col, FILE *fd, char *format, ...); 62 63 /* 64 * Add new definitions for the current disk/partition to a format data file. 65 */ 66 int 67 add_definition(void) 68 { 69 FILE *fd; 70 char *filename; 71 time_t clock; 72 char *prompt; 73 union { 74 int xfoo; 75 char deflt_str[MAXPATHLEN]; 76 } x; 77 78 /* 79 * There must be a current disk and partition table 80 */ 81 if (cur_disk == NULL) { 82 err_print("No Current Disk.\n"); 83 return (0); 84 } 85 if (cur_dtype == NULL) { 86 err_print("Current disk type is not set.\n"); 87 return (-1); 88 } 89 if (cur_parts == NULL) { 90 err_print("Current partition is not set.\n"); 91 return (-1); 92 } 93 /* 94 * If neither the disk definition nor the partition 95 * information has been changed, there's nothing to save. 96 */ 97 if (cur_dtype->dtype_filename != NULL && 98 cur_parts->pinfo_filename != NULL) { 99 err_print("\ 100 Neither the disk type nor the partitioning has been changed.\n"); 101 return (-1); 102 } 103 /* 104 * If saving the partition, and it's unnamed, the user should name 105 * it first. 106 */ 107 if (cur_parts->pinfo_name == NULL) { 108 assert(cur_parts->pinfo_filename == NULL); 109 err_print("Please name this partition type before saving it\n"); 110 return (-1); 111 } 112 /* 113 * Let the user know what we're doing 114 */ 115 if (cur_dtype->dtype_filename == NULL && 116 cur_parts->pinfo_filename == NULL) { 117 fmt_print("Saving new disk and partition definitions\n"); 118 } else if (cur_dtype->dtype_filename == NULL) { 119 fmt_print("Saving new disk definition\n"); 120 } else { 121 assert(cur_parts->pinfo_filename == NULL); 122 fmt_print("Saving new partition definition\n"); 123 } 124 /* 125 * Ask for the file to which to append the new definitions 126 */ 127 prompt = "Enter file name"; 128 (void) strcpy(x.deflt_str, "./format.dat"); 129 filename = (char *)(uintptr_t)input(FIO_OSTR, prompt, 130 ':', NULL, &x.xfoo, DATA_INPUT); 131 assert(filename != NULL); 132 /* 133 * Open the file in append mode, or create it, if necessary 134 */ 135 if ((fd = fopen(filename, "a")) == NULL) { 136 err_print("Cannot open `%s' - %s\n", filename, 137 strerror(errno)); 138 destroy_data(filename); 139 return (-1); 140 } 141 /* 142 * Write a header for the new definitions 143 */ 144 if ((cur_dtype->dtype_filename == NULL) && 145 (cur_parts->pinfo_filename == NULL)) { 146 (void) fprintf(fd, "#\n# New disk/partition type "); 147 } else if (cur_dtype->dtype_filename == NULL) { 148 (void) fprintf(fd, "#\n# New disk type "); 149 } else { 150 (void) fprintf(fd, "#\n# New partition type "); 151 } 152 (void) time(&clock); 153 (void) fprintf(fd, " saved on %s#\n", ctime(&clock)); 154 /* 155 * Save the new definitions 156 */ 157 if (cur_dtype->dtype_filename == NULL) { 158 add_disktype(fd, cur_disk); 159 } 160 if (cur_parts->pinfo_filename == NULL) { 161 add_partition(fd, cur_disk, cur_parts); 162 } 163 /* 164 * We're finished. Clean up 165 */ 166 (void) fclose(fd); 167 destroy_data(filename); 168 return (0); 169 } 170 171 /* 172 * Add a disk_type definition to the file fd 173 */ 174 static void 175 add_disktype(FILE *fd, struct disk_info *disk_info) 176 { 177 int col; 178 struct disk_type *disk_type; 179 180 disk_type = disk_info->disk_type; 181 182 (void) fprintf(fd, "disk_type = \"%s\" \\\n", 183 disk_type->dtype_asciilabel); 184 col = add_entry(0, fd, " : ctlr = %s", 185 ((disk_info->disk_ctlr)->ctlr_ctype)->ctype_name); 186 187 col = add_entry(col, fd, " : ncyl = %d", disk_type->dtype_ncyl); 188 189 col = add_entry(col, fd, " : acyl = %d", disk_type->dtype_acyl); 190 191 col = add_entry(col, fd, " : pcyl = %d", disk_type->dtype_pcyl); 192 193 col = add_entry(col, fd, " : nhead = %d", disk_type->dtype_nhead); 194 195 if (disk_type->dtype_options & SUP_PHEAD) { 196 col = add_entry(col, fd, " : phead = %d", 197 disk_type->dtype_phead); 198 } 199 200 col = add_entry(col, fd, " : nsect = %d", disk_type->dtype_nsect); 201 202 if (disk_type->dtype_options & SUP_PSECT) { 203 col = add_entry(col, fd, " : psect = %d", 204 disk_type->dtype_psect); 205 } 206 207 if (disk_type->dtype_options & SUP_BPT) { 208 col = add_entry(col, fd, " : bpt = %d", disk_type->dtype_bpt); 209 } 210 211 col = add_entry(col, fd, " : rpm = %d", disk_type->dtype_rpm); 212 213 if (disk_type->dtype_options & SUP_FMTTIME) { 214 col = add_entry(col, fd, " : fmt_time = %d", 215 disk_type->dtype_fmt_time); 216 } 217 218 if (disk_type->dtype_options & SUP_CYLSKEW) { 219 col = add_entry(col, fd, " : cyl_skew = %d", 220 disk_type->dtype_cyl_skew); 221 } 222 223 if (disk_type->dtype_options & SUP_TRKSKEW) { 224 col = add_entry(col, fd, " : trk_skew = %d", 225 disk_type->dtype_trk_skew); 226 } 227 228 if (disk_type->dtype_options & SUP_TRKS_ZONE) { 229 col = add_entry(col, fd, " : trks_zone = %d", 230 disk_type->dtype_trks_zone); 231 } 232 233 if (disk_type->dtype_options & SUP_ATRKS) { 234 col = add_entry(col, fd, " : atrks = %d", 235 disk_type->dtype_atrks); 236 } 237 238 if (disk_type->dtype_options & SUP_ASECT) { 239 col = add_entry(col, fd, " : asect = %d", 240 disk_type->dtype_asect); 241 } 242 243 if (disk_type->dtype_options & SUP_CACHE) { 244 col = add_entry(col, fd, " : cache = %d", 245 disk_type->dtype_cache); 246 } 247 248 if (disk_type->dtype_options & SUP_PREFETCH) { 249 col = add_entry(col, fd, " : prefetch = %d", 250 disk_type->dtype_threshold); 251 } 252 253 if (disk_type->dtype_options & SUP_CACHE_MIN) { 254 col = add_entry(col, fd, " : min_prefetch = %d", 255 disk_type->dtype_prefetch_min); 256 } 257 258 if (disk_type->dtype_options & SUP_CACHE_MAX) { 259 col = add_entry(col, fd, " : max_prefetch = %d", 260 disk_type->dtype_prefetch_max); 261 } 262 263 if (disk_type->dtype_options & SUP_BPS) { 264 col = add_entry(col, fd, " : bps = %d", 265 disk_type->dtype_bps); 266 } 267 268 if (disk_type->dtype_options & SUP_DRTYPE) { 269 col = add_entry(col, fd, " : drive_type = %d", 270 disk_type->dtype_dr_type); 271 } 272 273 /* 274 * Terminate the last line, and print one blank line 275 */ 276 (void) fprintf(fd, col == 0 ? "\n" : "\n\n"); 277 } 278 279 280 281 /* 282 * Once we exceed this length, wrap to a new line 283 */ 284 #define MAX_COLUMNS 50 285 286 /* 287 * Add a partition definition to the file fd 288 */ 289 static void 290 add_partition(FILE *fd, struct disk_info *disk_info, 291 struct partition_info *part) 292 { 293 int col; 294 int i; 295 struct disk_type *disk_type; 296 struct dk_map32 *pp; 297 char *s; 298 299 #if defined(_SUNOS_VTOC_8) 300 struct dk_map2 *pv; 301 302 #elif defined(_SUNOS_VTOC_16) 303 struct dkl_partition *pv; 304 305 #else 306 #error No VTOC format defined. 307 #endif /* defined (_SUNOS_VTOC_8) */ 308 struct dk_map2 *dv; 309 310 disk_type = disk_info->disk_type; 311 312 (void) fprintf(fd, "partition = \"%s\" \\\n", part->pinfo_name); 313 (void) fprintf(fd, "\t : disk = \"%s\" : ctlr = %s \\\n", 314 disk_type->dtype_asciilabel, 315 ((disk_info->disk_ctlr)->ctlr_ctype)->ctype_name); 316 317 /* 318 * Print the specifications for each useful partition 319 */ 320 col = 0; 321 pp = part->pinfo_map; 322 pv = part->vtoc.v_part; 323 dv = default_vtoc_map; 324 for (i = 0; i < NDKMAP; i++, pp++, pv++, dv++) { 325 if (pp->dkl_nblk != 0) { 326 col = add_entry(col, fd, " : %c = ", 327 i + PARTITION_BASE); 328 if (pv->p_tag != dv->p_tag || 329 pv->p_flag != dv->p_flag) { 330 s = find_string(ptag_choices, (int)pv->p_tag); 331 if (s != NULL) { 332 col = add_entry(col, fd, " %s,", s); 333 } 334 s = find_string(pflag_choices, (int)pv->p_flag); 335 if (s != NULL) { 336 col = add_entry(col, fd, " %s,", s); 337 } 338 } 339 col = add_entry(col, fd, " %d, %d", pp->dkl_cylno, 340 pp->dkl_nblk); 341 } 342 } 343 344 /* 345 * Terminate the last line, and print one blank line 346 */ 347 (void) fprintf(fd, col == 0 ? "\n" : "\n\n"); 348 } 349 350 /* 351 * Add an entry to the file fd. col is the current starting column. 352 * Return the resulting new column position. 353 */ 354 /*PRINTFLIKE3*/ 355 static int 356 add_entry(int col, FILE *fd, char *format, ...) 357 { 358 va_list ap; 359 va_start(ap, format); 360 361 if (col > MAX_COLUMNS) { 362 (void) fprintf(fd, " \\\n"); 363 col = 0; 364 } 365 if (col == 0) { 366 col += fprintf(fd, "\t"); 367 } 368 col += vfprintf(fd, format, ap); 369 va_end(ap); 370 371 return (col); 372 } 373