source: MondoRescue/branches/3.3/mindi-busybox/miscutils/eject.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 3.5 KB
RevLine 
[821]1/* vi: set sw=4 ts=4: */
2/*
3 * eject implementation for busybox
4 *
5 * Copyright (C) 2004 Peter Willis <psyphreak@phreaker.net>
6 * Copyright (C) 2005 Tito Ragusa <farmatito@tiscali.it>
7 *
[2725]8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
[821]9 */
10
11/*
12 * This is a simple hack of eject based on something Erik posted in #uclibc.
13 * Most of the dirty work blatantly ripped off from cat.c =)
14 */
15
[3232]16//usage:#define eject_trivial_usage
17//usage: "[-t] [-T] [DEVICE]"
18//usage:#define eject_full_usage "\n\n"
19//usage: "Eject DEVICE or default /dev/cdrom\n"
20//usage: IF_FEATURE_EJECT_SCSI(
21//usage: "\n -s SCSI device"
22//usage: )
23//usage: "\n -t Close tray"
24//usage: "\n -T Open/close tray (toggle)"
25
[2725]26#include <sys/mount.h>
[1765]27#include "libbb.h"
[3621]28#if ENABLE_FEATURE_EJECT_SCSI
[2725]29/* Must be after libbb.h: they need size_t */
[3621]30# include "fix_u32.h"
31# include <scsi/sg.h>
32# include <scsi/scsi.h>
33#endif
[821]34
[2725]35#define dev_fd 3
36
37/* Code taken from the original eject (http://eject.sourceforge.net/),
38 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */
39
[3621]40#if ENABLE_FEATURE_EJECT_SCSI
[2725]41static void eject_scsi(const char *dev)
42{
[3621]43 static const char sg_commands[3][6] ALIGN1 = {
[2725]44 { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
45 { START_STOP, 0, 0, 0, 1, 0 },
46 { START_STOP, 0, 0, 0, 2, 0 }
47 };
48
49 unsigned i;
50 unsigned char sense_buffer[32];
51 unsigned char inqBuff[2];
52 sg_io_hdr_t io_hdr;
53
54 if ((ioctl(dev_fd, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000))
55 bb_error_msg_and_die("not a sg device or old sg driver");
56
57 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
58 io_hdr.interface_id = 'S';
59 io_hdr.cmd_len = 6;
60 io_hdr.mx_sb_len = sizeof(sense_buffer);
61 io_hdr.dxfer_direction = SG_DXFER_NONE;
62 /* io_hdr.dxfer_len = 0; */
63 io_hdr.dxferp = inqBuff;
64 io_hdr.sbp = sense_buffer;
65 io_hdr.timeout = 2000;
66
67 for (i = 0; i < 3; i++) {
68 io_hdr.cmdp = (void *)sg_commands[i];
69 ioctl_or_perror_and_die(dev_fd, SG_IO, (void *)&io_hdr, "%s", dev);
70 }
71
72 /* force kernel to reread partition table when new disc is inserted */
73 ioctl(dev_fd, BLKRRPART);
74}
[3621]75#else
76# define eject_scsi(dev) ((void)0)
77#endif
[2725]78
[3621]79/* various defines swiped from linux/cdrom.h */
80#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
81#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
82#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
83/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
84#define CDS_TRAY_OPEN 2
85
[1765]86#define FLAG_CLOSE 1
87#define FLAG_SMART 2
[2725]88#define FLAG_SCSI 4
[1765]89
[2725]90static void eject_cdrom(unsigned flags, const char *dev)
[821]91{
[2725]92 int cmd = CDROMEJECT;
93
94 if (flags & FLAG_CLOSE
95 || ((flags & FLAG_SMART) && ioctl(dev_fd, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN)
96 ) {
97 cmd = CDROMCLOSETRAY;
98 }
99
100 ioctl_or_perror_and_die(dev_fd, cmd, NULL, "%s", dev);
101}
102
103int eject_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
104int eject_main(int argc UNUSED_PARAM, char **argv)
105{
106 unsigned flags;
[1765]107 const char *device;
[821]108
[1765]109 opt_complementary = "?1:t--T:T--t";
[2725]110 flags = getopt32(argv, "tT" IF_FEATURE_EJECT_SCSI("s"));
111 device = argv[optind] ? argv[optind] : "/dev/cdrom";
[821]112
[2725]113 /* We used to do "umount <device>" here, but it was buggy
114 if something was mounted OVER cdrom and
115 if cdrom is mounted many times.
[1765]116
[2725]117 This works equally well (or better):
118 #!/bin/sh
119 umount /dev/cdrom
120 eject /dev/cdrom
121 */
[1765]122
[2725]123 xmove_fd(xopen_nonblocking(device), dev_fd);
[1765]124
[2725]125 if (ENABLE_FEATURE_EJECT_SCSI && (flags & FLAG_SCSI))
126 eject_scsi(device);
127 else
128 eject_cdrom(flags, device);
129
[1765]130 if (ENABLE_FEATURE_CLEAN_UP)
[2725]131 close(dev_fd);
[1765]132
133 return EXIT_SUCCESS;
[821]134}
Note: See TracBrowser for help on using the repository browser.