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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <fcntl.h> 30 #include <stdio.h> 31 #include <sys/param.h> 32 #include <sys/stat.h> 33 #include <sys/time.h> 34 #include <sys/types.h> 35 #include <sys/file.h> 36 #include <sys/cdio.h> 37 #include <sys/dkio.h> 38 #include "hsfs_spec.h" 39 #include "iso_spec.h" 40 #include "iso_impl.h" 41 42 #define GETCDSECTOR(buf, secno, nosec) (getdisk(buf, \ 43 ((secno)+cdroff)*ISO_SECTOR_SIZE, \ 44 (nosec)*ISO_SECTOR_SIZE)) 45 char hs_buf[ISO_SECTOR_SIZE]; 46 int hs_pvd_sec_no; 47 char iso_buf[ISO_SECTOR_SIZE]; 48 int iso_pvd_sec_no; 49 char unix_buf[ISO_SECTOR_SIZE]; 50 int unix_pvd_sec_no; 51 52 int vflag; 53 int cdfd; 54 55 int cdroff = 0; 56 57 static int rdev_is_a_cd(int rdevfd); 58 static void getdisk(char *buf, int daddr, int size); 59 static void prntstring(char *heading, char *s, int maxlen); 60 static void prntlabel(int cd_type); 61 static void dumpfs(char *special); 62 static void usage(void); 63 64 int 65 main(int argc, char **argv) 66 { 67 int c; 68 char *special; 69 int errflag = 0; 70 71 while ((c = getopt(argc, argv, "v")) != EOF) { 72 switch (c) { 73 case 'v': 74 vflag++; 75 break; 76 default: 77 errflag++; 78 break; 79 } 80 } 81 82 if (errflag || (argc <= optind)) { 83 usage(); 84 exit(1); 85 } 86 87 special = argv[optind]; 88 89 dumpfs(special); 90 91 return (0); 92 } 93 94 static void 95 usage(void) 96 { 97 fprintf(stderr, "Usage: fstyp -v special\n"); 98 } 99 100 /* 101 * findhsvol: check if the disk is in high sierra format 102 * return(1) if found, (0) otherwise 103 * if found, volp will point to the descriptor 104 * 105 */ 106 int 107 findhsvol(volp) 108 char *volp; 109 { 110 int secno; 111 int i; 112 113 secno = HS_VOLDESC_SEC; 114 GETCDSECTOR(volp, secno++, 1); 115 while (HSV_DESC_TYPE(volp) != VD_EOV) { 116 for (i = 0; i < HSV_ID_STRLEN; i++) 117 if (HSV_STD_ID(volp)[i] != HSV_ID_STRING[i]) 118 goto cantfind; 119 if (HSV_STD_VER(volp) != HSV_ID_VER) 120 goto cantfind; 121 switch (HSV_DESC_TYPE(volp)) { 122 case VD_SFS: 123 hs_pvd_sec_no = secno-1; 124 return (1); 125 case VD_EOV: 126 goto cantfind; 127 } 128 GETCDSECTOR(volp, secno++, 1); 129 } 130 cantfind: 131 return (0); 132 } 133 134 /* 135 * findisovol: check if the disk is in ISO 9660 format 136 * return(1) if found, (0) otherwise 137 * if found, volp will point to the descriptor 138 * 139 */ 140 int 141 findisovol(volp) 142 char *volp; 143 { 144 int secno; 145 int i; 146 147 secno = ISO_VOLDESC_SEC; 148 GETCDSECTOR(volp, secno++, 1); 149 while (ISO_DESC_TYPE(volp) != ISO_VD_EOV) { 150 for (i = 0; i < ISO_ID_STRLEN; i++) 151 if (ISO_STD_ID(volp)[i] != ISO_ID_STRING[i]) 152 goto cantfind; 153 if (ISO_STD_VER(volp) != ISO_ID_VER) 154 goto cantfind; 155 switch (ISO_DESC_TYPE(volp)) { 156 case ISO_VD_PVD: 157 iso_pvd_sec_no = secno-1; 158 return (1); 159 case ISO_VD_EOV: 160 goto cantfind; 161 } 162 GETCDSECTOR(volp, secno++, 1); 163 } 164 cantfind: 165 return (0); 166 } 167 168 /* 169 * findunixvol: check if the disk is in UNIX extension format 170 * return(1) if found, (0) otherwise 171 * if found, volp will point to the descriptor 172 * 173 */ 174 int 175 findunixvol(char *volp) 176 { 177 int secno; 178 int i; 179 180 secno = ISO_VOLDESC_SEC; 181 GETCDSECTOR(volp, secno++, 1); 182 while (ISO_DESC_TYPE(volp) != ISO_VD_EOV) { 183 for (i = 0; i < ISO_ID_STRLEN; i++) 184 if (ISO_STD_ID(volp)[i] != ISO_ID_STRING[i]) 185 goto cantfind; 186 if (ISO_STD_VER(volp) != ISO_ID_VER) 187 goto cantfind; 188 switch (ISO_DESC_TYPE(volp)) { 189 case ISO_VD_UNIX: 190 unix_pvd_sec_no = secno-1; 191 return (1); 192 case ISO_VD_EOV: 193 goto cantfind; 194 } 195 GETCDSECTOR(volp, secno++, 1); 196 } 197 cantfind: 198 return (0); 199 } 200 201 int 202 ckvoldesc(void) 203 { 204 int cd_type; 205 206 if (findhsvol(hs_buf)) 207 cd_type = 0; 208 else if (findisovol(iso_buf)) { 209 if (findunixvol(unix_buf)) 210 cd_type = 2; 211 else cd_type = 1; 212 } else { 213 cd_type = -1; 214 } 215 216 return (cd_type); 217 218 } 219 220 static void 221 dumpfs(char *special) 222 { 223 int err; 224 int cd_type; 225 226 if ((cdfd = open(special, O_RDONLY)) < 0) { 227 fprintf(stderr, "hsfs fstyp: cannot open <%s>\n", special); 228 exit(1); 229 } 230 231 #ifdef CDROMREADOFFSET 232 if (rdev_is_a_cd(cdfd)) { 233 err = ioctl(cdfd, CDROMREADOFFSET, &cdroff); 234 if (err == -1) 235 /* 236 * This device doesn't support this ioctl. 237 * That's OK. 238 */ 239 cdroff = 0; 240 } 241 #endif 242 /* check volume descriptor */ 243 cd_type = ckvoldesc(); 244 245 if (cd_type < 0) 246 exit(1); 247 else 248 fprintf(stdout, "hsfs\n"); 249 250 if (vflag) 251 prntlabel(cd_type); 252 253 exit(0); 254 } 255 256 static void 257 prntlabel(int cd_type) 258 { 259 char *vdp; 260 char *sysid; 261 char *volid; 262 char *volsetid; 263 char *pubid; 264 char *prepid; 265 char *applid; 266 char *copyfile; 267 char *absfile; 268 char *bibfile; 269 int volsetsize; 270 int volsetseq; 271 int blksize; 272 int volsize; 273 int i; 274 275 switch (cd_type) { 276 case 0: 277 fprintf(stdout, "CD-ROM is in High Sierra format\n"); 278 sysid = (char *)HSV_sys_id(hs_buf); 279 volid = (char *)HSV_vol_id(hs_buf); 280 volsetid = (char *)HSV_vol_set_id(hs_buf); 281 pubid = (char *)HSV_pub_id(hs_buf); 282 prepid = (char *)HSV_prep_id(hs_buf); 283 applid = (char *)HSV_appl_id(hs_buf); 284 copyfile = (char *)HSV_copyr_id(hs_buf); 285 absfile = (char *)HSV_abstr_id(hs_buf); 286 bibfile = NULL; 287 volsetsize = HSV_SET_SIZE(hs_buf); 288 volsetseq = HSV_SET_SEQ(hs_buf); 289 blksize = HSV_BLK_SIZE(hs_buf); 290 volsize = HSV_VOL_SIZE(hs_buf); 291 break; 292 case 1: 293 fprintf(stdout, "CD-ROM is in ISO 9660 format\n"); 294 sysid = (char *)ISO_sys_id(iso_buf); 295 volid = (char *)ISO_vol_id(iso_buf); 296 volsetid = (char *)ISO_vol_set_id(iso_buf); 297 pubid = (char *)ISO_pub_id(iso_buf); 298 prepid = (char *)ISO_prep_id(iso_buf); 299 applid = (char *)ISO_appl_id(iso_buf); 300 copyfile = (char *)ISO_copyr_id(iso_buf); 301 absfile = (char *)ISO_abstr_id(iso_buf); 302 bibfile = (char *)ISO_bibli_id(iso_buf); 303 volsetsize = ISO_SET_SIZE(iso_buf); 304 volsetseq = ISO_SET_SEQ(iso_buf); 305 blksize = ISO_BLK_SIZE(iso_buf); 306 volsize = ISO_VOL_SIZE(iso_buf); 307 break; 308 case 2: 309 fprintf(stdout, "CD-ROM is in ISO 9660 format with" 310 " UNIX extension\n"); 311 sysid = (char *)ISO_sys_id(unix_buf); 312 volid = (char *)ISO_vol_id(unix_buf); 313 volsetid = (char *)ISO_vol_set_id(unix_buf); 314 pubid = (char *)ISO_pub_id(unix_buf); 315 prepid = (char *)ISO_prep_id(unix_buf); 316 applid = (char *)ISO_appl_id(unix_buf); 317 copyfile = (char *)ISO_copyr_id(unix_buf); 318 absfile = (char *)ISO_abstr_id(unix_buf); 319 bibfile = (char *)ISO_bibli_id(unix_buf); 320 volsetsize = ISO_SET_SIZE(unix_buf); 321 volsetseq = ISO_SET_SEQ(unix_buf); 322 blksize = ISO_BLK_SIZE(unix_buf); 323 volsize = ISO_VOL_SIZE(unix_buf); 324 break; 325 default: 326 return; 327 } 328 /* system id */ 329 prntstring("System id", sysid, 32); 330 /* read volume id */ 331 prntstring("Volume id", volid, 32); 332 /* read volume set id */ 333 prntstring("Volume set id", volsetid, 128); 334 /* publisher id */ 335 prntstring("Publisher id", pubid, 128); 336 /* data preparer id */ 337 prntstring("Data preparer id", prepid, 128); 338 /* application id */ 339 prntstring("Application id", applid, 128); 340 /* copyright file identifier */ 341 prntstring("Copyright File id", copyfile, 37); 342 /* Abstract file identifier */ 343 prntstring("Abstract File id", absfile, 37); 344 /* Bibliographic file identifier */ 345 prntstring("Bibliographic File id", bibfile, 37); 346 /* print volume set size */ 347 fprintf(stdout, "Volume set size is %d\n", volsetsize); 348 /* print volume set sequnce number */ 349 fprintf(stdout, "Volume set sequence number is %d\n", volsetseq); 350 /* print logical block size */ 351 fprintf(stdout, "Logical block size is %d\n", blksize); 352 /* print volume size */ 353 fprintf(stdout, "Volume size is %d\n", volsize); 354 } 355 356 static void 357 prntstring(char *heading, char *s, int maxlen) 358 { 359 int i; 360 if (maxlen < 1) 361 return; 362 if (heading == NULL || s == NULL) 363 return; 364 /* print heading */ 365 fprintf(stdout, "%s: ", heading); 366 367 /* strip off trailing zeros */ 368 for (i = maxlen-1; i >= 0; i--) 369 if (s[i] != ' ') break; 370 371 maxlen = i+1; 372 for (i = 0; i < maxlen; i++) 373 fprintf(stdout, "%c", s[i]); 374 fprintf(stdout, "\n"); 375 } 376 377 /* readdisk - read from cdrom image file */ 378 static void 379 getdisk(char *buf, int daddr, int size) 380 { 381 if (lseek(cdfd, daddr, L_SET) == -1) { 382 perror("getdisk/lseek"); 383 exit(1); 384 } 385 if (read(cdfd, buf, size) != size) { 386 perror("getdisk/read"); 387 exit(1); 388 } 389 } 390 391 /* 392 * rdev_is_a_cd - return TRUE if the raw device identified by 393 * a file descriptor is a CDROM device. 394 * 395 * return FALSE if the device can't be accessed 396 * or is not a CDROM. 397 */ 398 static int 399 rdev_is_a_cd(int rdevfd) 400 { 401 struct dk_cinfo dkc; 402 403 if (ioctl(rdevfd, DKIOCINFO, &dkc) < 0) 404 return (0); 405 if (dkc.dki_ctype == DKC_CDROM) 406 return (1); 407 else 408 return (0); 409 } 410