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