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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <sys/types.h> 31 #include <limits.h> 32 #include <unistd.h> 33 #include <libintl.h> 34 #include <locale.h> 35 #include <dbus/dbus.h> 36 #include <hal/libhal.h> 37 38 #include "msgs.h" 39 #include "device.h" 40 #include "util.h" 41 #include "main.h" 42 #include "options.h" 43 #include "mmc.h" 44 #include "misc_scsi.h" 45 46 /* 47 * global flags 48 */ 49 int debug = 0; 50 int keep_disc_open = 0; 51 int requested_speed = 0; 52 int simulation = 0; 53 int verbose = 0; 54 char *image_file = NULL; 55 char *blanking_type = NULL; 56 int audio_type = AUDIO_TYPE_NONE; 57 int extract_track_no = 0; 58 char *extract_file = NULL; 59 char *alt_tmp_dir = NULL; 60 char *copy_src = NULL; 61 int vol_running = 0; 62 int cflag = 0; 63 int tflag = 0; 64 uid_t ruid, cur_uid; 65 66 /* 67 * global variables 68 */ 69 cd_device *target = NULL; /* Default target device */ 70 static char *tgtdev = NULL; 71 int device_type = CD_RW; /* Default to CD/RW */ 72 int write_mode = TAO_MODE; /* Default to track at once */ 73 74 static void 75 print_usage(void) 76 { 77 err_msg(gettext("USAGE:\n")); 78 err_msg(gettext("\tcdrw -i [ -vSCO ] [ -d device ] [ -p speed ]")); 79 err_msg(gettext(" [ image-file ]\n")); 80 err_msg(gettext("\tcdrw -a [ -vSCO ] [ -d device ] [ -p speed ]")); 81 err_msg(gettext(" [ -T audio-type ] audio-file1 audio-file2 ...\n")); 82 err_msg(gettext("\tcdrw -x [ -v ] [ -d device ] [ -T audio-type ]")); 83 err_msg(gettext(" track-number audio-file\n")); 84 err_msg(gettext("\tcdrw -c [ -SC ] [ -d device ] [ -p speed ]")); 85 err_msg(gettext(" [ -m tmp-dir ] [ -s src-device ]\n")); 86 err_msg( 87 gettext("\tcdrw -b [ -v ] [ -d device ] all | session | fast\n")); 88 err_msg(gettext("\tcdrw -M [ -v ] [ -d device ]\n")); 89 err_msg(gettext("\tcdrw -L [ -v ] [ -d device ]\n")); 90 err_msg(gettext("\tcdrw -l [ -v ]\n")); 91 err_msg(gettext("\tcdrw -h\n")); 92 93 exit(2); 94 } 95 96 static void 97 check_invalid_option(options *specified, char *opstr) 98 { 99 options c_op; 100 int ret; 101 102 set_options_mask(&c_op, opstr); 103 if ((ret = compare_options_mask(&c_op, specified)) != 0) { 104 err_msg( 105 gettext("Option %c is not defined for this operation.\n"), 106 (char)ret); 107 print_usage(); 108 } 109 } 110 111 LibHalContext * 112 attach_to_hald(void) 113 { 114 LibHalContext *ctx = NULL; 115 DBusConnection *con = NULL; 116 DBusError error; 117 hal_state_t state; 118 119 /* Initialize the dbus error states */ 120 dbus_error_init(&error); 121 122 if ((con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == NULL) { 123 return (NULL); 124 } 125 state = DBUS_CONNECTION; 126 127 /* Allocate a new hal context to work with the dbus */ 128 if ((ctx = libhal_ctx_new()) == NULL) 129 return (NULL); 130 state = HAL_CONTEXT; 131 132 /* Pair up the context with the connection */ 133 if (!libhal_ctx_set_dbus_connection(ctx, con)) 134 goto fail; 135 state = HAL_PAIRED; 136 137 /* If libhal_ctx_init fails hald is not present */ 138 if (!libhal_ctx_init(ctx, &error)) { 139 goto fail; 140 } 141 state = HAL_INITIALIZED; 142 143 return (ctx); 144 fail: 145 if (dbus_error_is_set(&error)) 146 dbus_error_free(&error); 147 detach_from_hald(ctx, state); 148 return (NULL); 149 150 } 151 152 void 153 detach_from_hald(LibHalContext *ctx, hal_state_t state) 154 { 155 DBusError error; 156 DBusConnection *con = libhal_ctx_get_dbus_connection(ctx); 157 158 dbus_error_init(&error); 159 160 switch (state) { 161 case HAL_INITIALIZED: 162 if (libhal_ctx_shutdown(ctx, &error) == FALSE) 163 if (dbus_error_is_set(&error)) 164 dbus_error_free(&error); 165 /*FALLTHROUGH*/ 166 case HAL_PAIRED: 167 (void) libhal_ctx_free(ctx); 168 dbus_connection_unref(con); 169 break; 170 case HAL_CONTEXT: 171 (void) libhal_ctx_free(ctx); 172 break; 173 case DBUS_CONNECTION: 174 default: 175 break; 176 } 177 } 178 179 /* 180 * This function returns one if hald is running and 181 * zero if hald is not running 182 */ 183 int 184 hald_running(void) 185 { 186 LibHalContext *ctx; 187 188 if ((ctx = attach_to_hald()) == NULL) 189 return (0); 190 191 detach_from_hald(ctx, HAL_INITIALIZED); 192 return (1); 193 } 194 195 int 196 setup_target(int flag) 197 { 198 char *devpath; 199 200 if (tgtdev != NULL) { 201 devpath = (char *)my_zalloc(PATH_MAX); 202 if (lookup_device(tgtdev, devpath)) { 203 target = get_device(tgtdev, devpath); 204 } 205 free(devpath); 206 if (target == NULL) { 207 return (0); 208 } 209 return (1); 210 } 211 return (scan_for_cd_device(flag, &target)); 212 } 213 214 int 215 main(int argc, char **argv) 216 { 217 int c; 218 int operations; 219 options specified_ops; 220 int aflag, iflag, Mflag, Lflag, lflag, bflag, xflag; 221 int ret; 222 223 (void) setlocale(LC_ALL, ""); 224 225 #if !defined(TEXT_DOMAIN) 226 #define TEXT_DOMAIN "SYS_TEST" 227 #endif 228 229 230 (void) textdomain(TEXT_DOMAIN); 231 232 ruid = getuid(); 233 cur_uid = geteuid(); 234 235 if (check_auth(ruid) != 1) { 236 err_msg(gettext( 237 "Authorization failed, Cannot access disks.\n")); 238 exit(1); 239 } 240 241 if ((cur_uid == 0) && (ruid != 0)) { 242 priv_change_needed = 1; 243 lower_priv(); 244 } 245 246 vol_running = hald_running(); 247 248 tgtdev = NULL; 249 operations = 0; 250 set_options_mask(&specified_ops, ""); 251 iflag = Mflag = Lflag = lflag = bflag = aflag = xflag = cflag = 0; 252 253 while ((c = getopt(argc, argv, "abcCd:hiLlm:MOp:s:ST:vVx")) != EOF) { 254 add_option(&specified_ops, c); 255 switch (c) { 256 case 'a': 257 aflag = 1; 258 operations++; 259 break; 260 case 'b': 261 bflag = 1; 262 operations++; 263 break; 264 case 'c': 265 cflag = 1; 266 operations++; 267 break; 268 case 'C': 269 /* 270 * cdrw now attempts to use the stated medium capacity 271 * by default, so this option no longer has any effect. 272 * It remains in the interface for backwards 273 * compatibility only. 274 */ 275 break; 276 case 'd': 277 tgtdev = optarg; 278 break; 279 case 'h': 280 print_usage(); /* will not return */ 281 break; 282 case 'i': 283 iflag = 1; 284 operations++; 285 break; 286 case 'L': 287 Lflag = 1; 288 operations++; 289 break; 290 case 'l': 291 lflag = 1; 292 operations++; 293 break; 294 case 'm': 295 alt_tmp_dir = optarg; 296 break; 297 case 'M': 298 Mflag = 1; 299 operations++; 300 break; 301 case 'O': 302 keep_disc_open = 1; 303 break; 304 case 'p': 305 requested_speed = atoi(optarg); 306 break; 307 case 's': 308 copy_src = optarg; 309 break; 310 case 'S': 311 simulation++; 312 break; 313 case 'T': 314 audio_type = get_audio_type(optarg); 315 if (audio_type == -1) { 316 err_msg(gettext("Unknown audio type %s\n"), 317 optarg); 318 exit(1); 319 } 320 break; 321 case 'v': 322 verbose++; 323 break; 324 case 'V': 325 /* 326 * more verbose. this will print out debug comments 327 */ 328 329 debug++; 330 break; 331 case 'x': 332 xflag++; 333 operations++; 334 break; 335 default: 336 print_usage(); 337 } 338 } 339 if (operations == 0) { 340 err_msg(gettext("No operation specified.\n")); 341 exit(1); 342 } 343 if (operations != 1) { 344 err_msg(gettext("More than one operation specified.\n")); 345 exit(1); 346 } 347 348 if (lflag) { 349 check_invalid_option(&specified_ops, "lhvV"); 350 list(); 351 } 352 353 /* 354 * we'll allow the user to specify the source device (-s) when 355 * extracting audio. 356 */ 357 358 if (xflag && copy_src) 359 tgtdev = copy_src; 360 361 /* 362 * This will scan for all CD devices when xflag or Mflag 363 * (extract audio, list toc) commands are used, providing 364 * no CD-RW devices are found. Since these commands can 365 * be used without a CD writer. 366 */ 367 368 if (xflag || Mflag) { 369 ret = setup_target(SCAN_ALL_CDS); 370 } else { 371 ret = setup_target(SCAN_WRITERS); 372 } 373 374 if (ret == 0) { 375 376 if (tgtdev != NULL) { 377 err_msg(gettext( 378 "Cannot find device %s.\n"), tgtdev); 379 380 } 381 382 if (vol_running) { 383 err_msg(gettext( 384 "No CD writers found or no media in the drive.\n")); 385 } else { 386 if (cur_uid != 0) { 387 err_msg(gettext( 388 "Volume manager is not running.\n")); 389 err_msg(gettext( 390 "Please start volume manager or run cdrw as root to access all devices.\n")); 391 } else { 392 err_msg(gettext( 393 "No CD writers found.\n")); 394 } 395 } 396 exit(1); 397 398 } else if (ret != 1) { 399 err_msg(gettext("More than one CD device found.\n")); 400 err_msg(gettext("Specify one using -d option.\n")); 401 err_msg(gettext( 402 "Or use -l option to list all the CD devices found\n")); 403 exit(1); 404 } 405 (void) check_device(target, CHECK_TYPE_NOT_CDROM|EXIT_IF_CHECK_FAILED); 406 407 if (check_device(target, CHECK_NO_MEDIA) == 0) { 408 int retry; 409 for (retry = 0; retry < 5; retry++) { 410 if (check_device(target, CHECK_DEVICE_NOT_READY) == 0) 411 break; 412 (void) sleep(3); 413 } 414 } 415 416 if (aflag) { 417 check_invalid_option(&specified_ops, "ahvSCOdpTV"); 418 if (optind == argc) { 419 err_msg(gettext("No audio files specified.\n")); 420 exit(1); 421 } 422 write_audio(argv, optind, argc); 423 } 424 if (Mflag) { 425 check_invalid_option(&specified_ops, "MhvdV"); 426 info(); 427 } 428 if (iflag) { 429 check_invalid_option(&specified_ops, "ihvSCOdpV"); 430 if (optind == (argc - 1)) { 431 image_file = argv[optind]; 432 write_image(); 433 } 434 if (optind == argc) 435 write_image(); 436 err_msg(gettext("Command line parsing error.\n")); 437 err_msg(gettext("Only one image-file can be specified.\n")); 438 exit(1); 439 } 440 if (bflag) { 441 check_invalid_option(&specified_ops, "bhvdV"); 442 if (optind != (argc - 1)) { 443 err_msg(gettext("Command line parsing error.\n")); 444 print_usage(); 445 } 446 blanking_type = argv[argc - 1]; 447 blank(); 448 } 449 if (xflag) { 450 check_invalid_option(&specified_ops, "xhpvdsTV"); 451 if (optind != (argc - 2)) { 452 err_msg(gettext("Command line parsing error.\n")); 453 print_usage(); 454 } 455 extract_track_no = atoi(argv[argc - 2]); 456 extract_file = argv[argc - 1]; 457 extract_audio(); 458 } 459 if (cflag) { 460 check_invalid_option(&specified_ops, "chvSCdpmsV"); 461 copy_cd(); 462 } 463 464 /* 465 * Open a closed disk, we do this by erasing the track tail 466 * and then re-finalizing with an open leadout. 467 */ 468 if (Lflag) { 469 check_invalid_option(&specified_ops, "LvdV"); 470 (void) check_device(target, CHECK_NO_MEDIA | 471 CHECK_DEVICE_NOT_READY | EXIT_IF_CHECK_FAILED); 472 473 /* no need to erase blank media */ 474 if (!check_device(target, CHECK_MEDIA_IS_NOT_BLANK)) 475 exit(0); 476 477 blanking_type = "leadout"; 478 blank(); 479 480 write_init(TRACK_MODE_DATA); 481 (void) close_track(target->d_fd, 0, 1, 1); 482 (void) finalize(target); 483 (void) printf(gettext("done.\n")); 484 exit(0); 485 } 486 return (0); 487 } 488