xref: /aosp_15_r20/external/mtools/mzip.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1*d5c9a868SElliott Hughes /*  Copyright 1996 Grant R. Guenther,  based on work of Itai Nahshon
2*d5c9a868SElliott Hughes  *   http://www.torque.net/ziptool.html
3*d5c9a868SElliott Hughes  *  Copyright 1997-2002,2007-2009 Alain Knaff.
4*d5c9a868SElliott Hughes  *  This file is part of mtools.
5*d5c9a868SElliott Hughes  *
6*d5c9a868SElliott Hughes  *  Mtools is free software: you can redistribute it and/or modify
7*d5c9a868SElliott Hughes  *  it under the terms of the GNU General Public License as published by
8*d5c9a868SElliott Hughes  *  the Free Software Foundation, either version 3 of the License, or
9*d5c9a868SElliott Hughes  *  (at your option) any later version.
10*d5c9a868SElliott Hughes  *
11*d5c9a868SElliott Hughes  *  Mtools is distributed in the hope that it will be useful,
12*d5c9a868SElliott Hughes  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*d5c9a868SElliott Hughes  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*d5c9a868SElliott Hughes  *  GNU General Public License for more details.
15*d5c9a868SElliott Hughes  *
16*d5c9a868SElliott Hughes  *  You should have received a copy of the GNU General Public License
17*d5c9a868SElliott Hughes  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
18*d5c9a868SElliott Hughes  *
19*d5c9a868SElliott Hughes  * mzip.c
20*d5c9a868SElliott Hughes  * Iomega Zip/Jaz drive tool
21*d5c9a868SElliott Hughes  * change protection mode and eject disk
22*d5c9a868SElliott Hughes  */
23*d5c9a868SElliott Hughes 
24*d5c9a868SElliott Hughes /* mzip.c by Markus Gyger <[email protected]> */
25*d5c9a868SElliott Hughes /* This code is based on ftp://gear.torque.net/pub/ziptool.c */
26*d5c9a868SElliott Hughes /* by Grant R. Guenther with the following copyright notice: */
27*d5c9a868SElliott Hughes 
28*d5c9a868SElliott Hughes /*  (c) 1996   Grant R. Guenther,  based on work of Itai Nahshon  */
29*d5c9a868SElliott Hughes /*  http://www.torque.net/ziptool.html  */
30*d5c9a868SElliott Hughes 
31*d5c9a868SElliott Hughes 
32*d5c9a868SElliott Hughes /* Unprotect-till-eject modes and mount tests added
33*d5c9a868SElliott Hughes  * by Ilya Ovchinnikov <[email protected]>
34*d5c9a868SElliott Hughes  */
35*d5c9a868SElliott Hughes 
36*d5c9a868SElliott Hughes #include "sysincludes.h"
37*d5c9a868SElliott Hughes #include "mtools.h"
38*d5c9a868SElliott Hughes #include "scsi.h"
39*d5c9a868SElliott Hughes 
40*d5c9a868SElliott Hughes #ifndef _PASSWORD_LEN
41*d5c9a868SElliott Hughes #define _PASSWORD_LEN 33
42*d5c9a868SElliott Hughes #endif
43*d5c9a868SElliott Hughes 
44*d5c9a868SElliott Hughes #ifdef OS_linux
45*d5c9a868SElliott Hughes 
46*d5c9a868SElliott Hughes #if __GLIBC__ >=2
47*d5c9a868SElliott Hughes #include <sys/mount.h>
48*d5c9a868SElliott Hughes #else
49*d5c9a868SElliott Hughes #define _LINUX_KDEV_T_H 1  /* don't redefine MAJOR/MINOR */
50*d5c9a868SElliott Hughes #include <linux/fs.h>
51*d5c9a868SElliott Hughes #endif
52*d5c9a868SElliott Hughes 
53*d5c9a868SElliott Hughes #include "devices.h"
54*d5c9a868SElliott Hughes 
55*d5c9a868SElliott Hughes #endif
56*d5c9a868SElliott Hughes 
57*d5c9a868SElliott Hughes 
zip_cmd(int priv,int fd,unsigned char cdb[6],uint8_t clen,scsi_io_mode_t mode,void * data,uint32_t len,void * extra_data)58*d5c9a868SElliott Hughes static int zip_cmd(int priv, int fd, unsigned char cdb[6], uint8_t clen,
59*d5c9a868SElliott Hughes 		   scsi_io_mode_t mode, void *data, uint32_t len,
60*d5c9a868SElliott Hughes 		   void *extra_data)
61*d5c9a868SElliott Hughes {
62*d5c9a868SElliott Hughes 	int r;
63*d5c9a868SElliott Hughes 
64*d5c9a868SElliott Hughes 	if(priv)
65*d5c9a868SElliott Hughes 		reclaim_privs();
66*d5c9a868SElliott Hughes 	r = scsi_cmd(fd, cdb, clen,  mode, data, len, extra_data);
67*d5c9a868SElliott Hughes 	if(priv)
68*d5c9a868SElliott Hughes 		drop_privs();
69*d5c9a868SElliott Hughes 	return r;
70*d5c9a868SElliott Hughes }
71*d5c9a868SElliott Hughes 
test_mounted(char * dev UNUSEDP)72*d5c9a868SElliott Hughes static int test_mounted ( char *dev UNUSEDP)
73*d5c9a868SElliott Hughes {
74*d5c9a868SElliott Hughes #ifdef HAVE_MNTENT_H
75*d5c9a868SElliott Hughes 	struct mntent	*mnt;
76*d5c9a868SElliott Hughes 	struct MT_STAT	st_dev, st_mnt;
77*d5c9a868SElliott Hughes 	FILE		*mtab;
78*d5c9a868SElliott Hughes /*
79*d5c9a868SElliott Hughes  * Now check if any partition of this device is already mounted (this
80*d5c9a868SElliott Hughes  * includes checking if the device is mounted under a different name).
81*d5c9a868SElliott Hughes  */
82*d5c9a868SElliott Hughes 
83*d5c9a868SElliott Hughes 	if (MT_STAT (dev, &st_dev)) {
84*d5c9a868SElliott Hughes 		fprintf (stderr, "%s: stat(%s) failed: %s.\n",
85*d5c9a868SElliott Hughes 			 progname, dev, strerror (errno));
86*d5c9a868SElliott Hughes 		exit(1);
87*d5c9a868SElliott Hughes 	}
88*d5c9a868SElliott Hughes 
89*d5c9a868SElliott Hughes 	if (!S_ISBLK (st_dev.st_mode)) /* not a block device, cannot
90*d5c9a868SElliott Hughes 					* be mounted */
91*d5c9a868SElliott Hughes 		return 0;
92*d5c9a868SElliott Hughes 
93*d5c9a868SElliott Hughes #ifndef _PATH_MOUNTED
94*d5c9a868SElliott Hughes # define _PATH_MOUNTED "/etc/mtab"
95*d5c9a868SElliott Hughes #endif
96*d5c9a868SElliott Hughes 
97*d5c9a868SElliott Hughes 	if ((mtab = setmntent (_PATH_MOUNTED, "r")) == NULL) {
98*d5c9a868SElliott Hughes 		fprintf (stderr, "%s: can't open %s.\n",
99*d5c9a868SElliott Hughes 			 progname, _PATH_MOUNTED);
100*d5c9a868SElliott Hughes 		exit(1);
101*d5c9a868SElliott Hughes 	}
102*d5c9a868SElliott Hughes 
103*d5c9a868SElliott Hughes 	while ( ( mnt = getmntent (mtab) ) ) {
104*d5c9a868SElliott Hughes 		if (!mnt->mnt_fsname
105*d5c9a868SElliott Hughes 
106*d5c9a868SElliott Hughes #ifdef MNTTYPE_SWAP
107*d5c9a868SElliott Hughes 		    || !strcmp (mnt->mnt_type, MNTTYPE_SWAP)
108*d5c9a868SElliott Hughes #endif
109*d5c9a868SElliott Hughes #ifdef MNTTYPE_NFS
110*d5c9a868SElliott Hughes 		    || !strcmp (mnt->mnt_type, MNTTYPE_NFS)
111*d5c9a868SElliott Hughes #endif
112*d5c9a868SElliott Hughes 		    ||  !strcmp (mnt->mnt_type, "proc")
113*d5c9a868SElliott Hughes 		    ||  !strcmp (mnt->mnt_type, "smbfs")
114*d5c9a868SElliott Hughes #ifdef MNTTYPE_IGNORE
115*d5c9a868SElliott Hughes 		    ||  !strcmp (mnt->mnt_type, MNTTYPE_IGNORE)
116*d5c9a868SElliott Hughes #endif
117*d5c9a868SElliott Hughes 			)
118*d5c9a868SElliott Hughes 			continue;
119*d5c9a868SElliott Hughes 
120*d5c9a868SElliott Hughes 		if (MT_STAT (mnt->mnt_fsname, &st_mnt)) {
121*d5c9a868SElliott Hughes 			continue;
122*d5c9a868SElliott Hughes 		}
123*d5c9a868SElliott Hughes 
124*d5c9a868SElliott Hughes 		if (S_ISBLK (st_mnt.st_mode)) {
125*d5c9a868SElliott Hughes #ifdef OS_linux
126*d5c9a868SElliott Hughes 			/* on Linux, warn also if the device is on the same
127*d5c9a868SElliott Hughes 			 * partition */
128*d5c9a868SElliott Hughes 			if (MAJOR(st_mnt.st_rdev) == MAJOR(st_dev.st_rdev) &&
129*d5c9a868SElliott Hughes 			    MINOR(st_mnt.st_rdev) >= MINOR(st_dev.st_rdev) &&
130*d5c9a868SElliott Hughes 			    MINOR(st_mnt.st_rdev) <= MINOR(st_dev.st_rdev)+15){
131*d5c9a868SElliott Hughes 				fprintf (stderr,
132*d5c9a868SElliott Hughes 					 "Device %s%d is mounted on %s.\n",
133*d5c9a868SElliott Hughes 					 dev,
134*d5c9a868SElliott Hughes 					 MINOR(st_mnt.st_rdev) -
135*d5c9a868SElliott Hughes 					 MINOR(st_dev.st_rdev),
136*d5c9a868SElliott Hughes 					 mnt->mnt_dir);
137*d5c9a868SElliott Hughes #else
138*d5c9a868SElliott Hughes 				if(st_mnt.st_rdev != st_dev.st_rdev) {
139*d5c9a868SElliott Hughes #endif
140*d5c9a868SElliott Hughes 					endmntent (mtab);
141*d5c9a868SElliott Hughes 					return 1;
142*d5c9a868SElliott Hughes 				}
143*d5c9a868SElliott Hughes #if 0
144*d5c9a868SElliott Hughes 			} /* keep Emacs indentation happy */
145*d5c9a868SElliott Hughes #endif
146*d5c9a868SElliott Hughes 		}
147*d5c9a868SElliott Hughes 	}
148*d5c9a868SElliott Hughes 	endmntent (mtab);
149*d5c9a868SElliott Hughes #endif
150*d5c9a868SElliott Hughes 	return 0;
151*d5c9a868SElliott Hughes }
152*d5c9a868SElliott Hughes 
153*d5c9a868SElliott Hughes 
154*d5c9a868SElliott Hughes static void usage(int ret) NORETURN;
usage(int ret)155*d5c9a868SElliott Hughes static void usage(int ret)
156*d5c9a868SElliott Hughes {
157*d5c9a868SElliott Hughes 	fprintf(stderr,
158*d5c9a868SElliott Hughes 		"Mtools version %s, dated %s\n",
159*d5c9a868SElliott Hughes 		mversion, mdate);
160*d5c9a868SElliott Hughes 	fprintf(stderr,
161*d5c9a868SElliott Hughes 		"Usage: %s [-V] [-q] [-e] [-u] [-r|-w|-p|-x] [drive:]\n"
162*d5c9a868SElliott Hughes 		"\t-q print status\n"
163*d5c9a868SElliott Hughes 		"\t-e eject disk\n"
164*d5c9a868SElliott Hughes 		"\t-f eject disk even when mounted\n"
165*d5c9a868SElliott Hughes 		"\t-r write protected (read-only)\n"
166*d5c9a868SElliott Hughes 		"\t-w not write-protected (read-write)\n"
167*d5c9a868SElliott Hughes 		"\t-p password write protected\n"
168*d5c9a868SElliott Hughes 		"\t-x password protected\n"
169*d5c9a868SElliott Hughes 		"\t-u unprotect till disk ejecting\n",
170*d5c9a868SElliott Hughes 		progname);
171*d5c9a868SElliott Hughes 	exit(ret);
172*d5c9a868SElliott Hughes }
173*d5c9a868SElliott Hughes 
174*d5c9a868SElliott Hughes #define ZIP_RW (0)
175*d5c9a868SElliott Hughes #define ZIP_RO (2)
176*d5c9a868SElliott Hughes #define ZIP_RO_PW (3)
177*d5c9a868SElliott Hughes #define ZIP_PW (5)
178*d5c9a868SElliott Hughes #define ZIP_UNLOCK_TIL_EJECT (8)
179*d5c9a868SElliott Hughes 
get_zip_status(int priv,int fd,void * extra_data)180*d5c9a868SElliott Hughes static uint8_t get_zip_status(int priv, int fd, void *extra_data)
181*d5c9a868SElliott Hughes {
182*d5c9a868SElliott Hughes 	unsigned char status[128];
183*d5c9a868SElliott Hughes 	unsigned char cdb[6] = { 0x06, 0, 0x02, 0, sizeof status, 0 };
184*d5c9a868SElliott Hughes 
185*d5c9a868SElliott Hughes 	if (zip_cmd(priv, fd, cdb, 6, SCSI_IO_READ,
186*d5c9a868SElliott Hughes 		    status, sizeof status, extra_data) == -1) {
187*d5c9a868SElliott Hughes 		perror("status: ");
188*d5c9a868SElliott Hughes 		exit(1);
189*d5c9a868SElliott Hughes 	}
190*d5c9a868SElliott Hughes 	return status[21] & 0xf;
191*d5c9a868SElliott Hughes }
192*d5c9a868SElliott Hughes 
193*d5c9a868SElliott Hughes 
short_command(int priv,int fd,uint8_t cmd1,uint8_t cmd2,uint8_t cmd3,const char * data,void * extra_data)194*d5c9a868SElliott Hughes static int short_command(int priv, int fd, uint8_t cmd1, uint8_t cmd2,
195*d5c9a868SElliott Hughes 			 uint8_t cmd3, const char *data, void *extra_data)
196*d5c9a868SElliott Hughes {
197*d5c9a868SElliott Hughes 	uint8_t cdb[6] = { 0, 0, 0, 0, 0, 0 };
198*d5c9a868SElliott Hughes 
199*d5c9a868SElliott Hughes 	cdb[0] = cmd1;
200*d5c9a868SElliott Hughes 	cdb[1] = cmd2;
201*d5c9a868SElliott Hughes 	cdb[4] = cmd3;
202*d5c9a868SElliott Hughes 
203*d5c9a868SElliott Hughes 	return zip_cmd(priv, fd, cdb, 6, SCSI_IO_WRITE,
204*d5c9a868SElliott Hughes 		       (char *) data, data ? (uint32_t) strlen(data) : 0,
205*d5c9a868SElliott Hughes 		       extra_data);
206*d5c9a868SElliott Hughes }
207*d5c9a868SElliott Hughes 
208*d5c9a868SElliott Hughes 
iomega_command(int priv,int fd,uint8_t mode,const char * data,void * extra_data)209*d5c9a868SElliott Hughes static int iomega_command(int priv, int fd, uint8_t mode, const char *data,
210*d5c9a868SElliott Hughes 			  void *extra_data)
211*d5c9a868SElliott Hughes {
212*d5c9a868SElliott Hughes 	return short_command(priv, fd,
213*d5c9a868SElliott Hughes 			     SCSI_IOMEGA, mode,
214*d5c9a868SElliott Hughes 			     /* Do we really need strlen(data) in here? */
215*d5c9a868SElliott Hughes 			     data ? (uint8_t) strlen(data) : 0,
216*d5c9a868SElliott Hughes 			     data, extra_data);
217*d5c9a868SElliott Hughes }
218*d5c9a868SElliott Hughes 
door_command(int priv,int fd,uint8_t cmd1,uint8_t cmd2,void * extra_data)219*d5c9a868SElliott Hughes static int door_command(int priv, int fd, uint8_t cmd1, uint8_t cmd2,
220*d5c9a868SElliott Hughes 			void *extra_data)
221*d5c9a868SElliott Hughes {
222*d5c9a868SElliott Hughes 	return short_command(priv, fd, cmd1, 0, cmd2, 0, extra_data);
223*d5c9a868SElliott Hughes }
224*d5c9a868SElliott Hughes 
225*d5c9a868SElliott Hughes void mzip(int argc, char **argv, int type UNUSEDP) NORETURN;
mzip(int argc,char ** argv,int type UNUSEDP)226*d5c9a868SElliott Hughes void mzip(int argc, char **argv, int type UNUSEDP)
227*d5c9a868SElliott Hughes {
228*d5c9a868SElliott Hughes 	void *extra_data = NULL;
229*d5c9a868SElliott Hughes 	int c;
230*d5c9a868SElliott Hughes 	char drive;
231*d5c9a868SElliott Hughes 	device_t *dev;
232*d5c9a868SElliott Hughes 	int fd = -1;
233*d5c9a868SElliott Hughes 	char name[EXPAND_BUF];
234*d5c9a868SElliott Hughes #define ZIP_NIX (0)
235*d5c9a868SElliott Hughes #define ZIP_STATUS (1 << 0)
236*d5c9a868SElliott Hughes #define ZIP_EJECT  (1 << 1)
237*d5c9a868SElliott Hughes #define ZIP_MODE_CHANGE (1 << 2)
238*d5c9a868SElliott Hughes #define ZIP_FORCE  (1 << 3)
239*d5c9a868SElliott Hughes 	int request = ZIP_NIX;
240*d5c9a868SElliott Hughes 
241*d5c9a868SElliott Hughes 	uint8_t newMode = ZIP_RW;
242*d5c9a868SElliott Hughes 	uint8_t oldMode = ZIP_RW;
243*d5c9a868SElliott Hughes 
244*d5c9a868SElliott Hughes #define setMode(x) \
245*d5c9a868SElliott Hughes 	if(request & ZIP_MODE_CHANGE) usage(1); \
246*d5c9a868SElliott Hughes 	request |= ZIP_MODE_CHANGE; \
247*d5c9a868SElliott Hughes 	newMode = x; \
248*d5c9a868SElliott Hughes 	break
249*d5c9a868SElliott Hughes 
250*d5c9a868SElliott Hughes 	/* get command line options */
251*d5c9a868SElliott Hughes 	if(helpFlag(argc, argv))
252*d5c9a868SElliott Hughes 		usage(0);
253*d5c9a868SElliott Hughes 	while ((c = getopt(argc, argv, "i:efpqrwxuh")) != EOF) {
254*d5c9a868SElliott Hughes 		switch (c) {
255*d5c9a868SElliott Hughes 			case 'i':
256*d5c9a868SElliott Hughes 				set_cmd_line_image(optarg);
257*d5c9a868SElliott Hughes 				break;
258*d5c9a868SElliott Hughes 			case 'f':
259*d5c9a868SElliott Hughes 				if (get_real_uid()) {
260*d5c9a868SElliott Hughes 					fprintf(stderr,
261*d5c9a868SElliott Hughes 						"Only root can use force. Sorry.\n");
262*d5c9a868SElliott Hughes 					exit(1);
263*d5c9a868SElliott Hughes 				}
264*d5c9a868SElliott Hughes 				request |= ZIP_FORCE;
265*d5c9a868SElliott Hughes 				break;
266*d5c9a868SElliott Hughes 			case 'e': /* eject */
267*d5c9a868SElliott Hughes 				request |= ZIP_EJECT;
268*d5c9a868SElliott Hughes 				break;
269*d5c9a868SElliott Hughes 			case 'q': /* status query */
270*d5c9a868SElliott Hughes 				request |= ZIP_STATUS;
271*d5c9a868SElliott Hughes 				break;
272*d5c9a868SElliott Hughes 
273*d5c9a868SElliott Hughes 			case 'p': /* password read-only */
274*d5c9a868SElliott Hughes 				setMode(ZIP_RO_PW);
275*d5c9a868SElliott Hughes 			case 'r': /* read-only */
276*d5c9a868SElliott Hughes 				setMode(ZIP_RO);
277*d5c9a868SElliott Hughes 			case 'w': /* read-write */
278*d5c9a868SElliott Hughes 				setMode(ZIP_RW);
279*d5c9a868SElliott Hughes 			case 'x': /* password protected */
280*d5c9a868SElliott Hughes 				setMode(ZIP_PW);
281*d5c9a868SElliott Hughes 			case 'u': /* password protected */
282*d5c9a868SElliott Hughes 				setMode(ZIP_UNLOCK_TIL_EJECT);
283*d5c9a868SElliott Hughes 			case 'h':
284*d5c9a868SElliott Hughes 				usage(0);
285*d5c9a868SElliott Hughes 			default:  /* unrecognized */
286*d5c9a868SElliott Hughes 				usage(1);
287*d5c9a868SElliott Hughes 
288*d5c9a868SElliott Hughes 		}
289*d5c9a868SElliott Hughes 	}
290*d5c9a868SElliott Hughes 
291*d5c9a868SElliott Hughes 	if (request == ZIP_NIX) request = ZIP_STATUS;  /* default action */
292*d5c9a868SElliott Hughes 
293*d5c9a868SElliott Hughes 	if (argc - optind > 1 ||
294*d5c9a868SElliott Hughes 	    (argc - optind == 1 &&
295*d5c9a868SElliott Hughes 	     (!argv[optind][0] || argv[optind][1] != ':')))
296*d5c9a868SElliott Hughes 		usage(1);
297*d5c9a868SElliott Hughes 
298*d5c9a868SElliott Hughes 	drive = ch_toupper(argc - optind == 1 ? argv[argc - 1][0] : ':');
299*d5c9a868SElliott Hughes 
300*d5c9a868SElliott Hughes 	for (dev = devices; dev->name; dev++) {
301*d5c9a868SElliott Hughes 		unsigned char cdb[6] = { 0, 0, 0, 0, 0, 0 };
302*d5c9a868SElliott Hughes 		struct {
303*d5c9a868SElliott Hughes 			char    type,
304*d5c9a868SElliott Hughes 				type_modifier,
305*d5c9a868SElliott Hughes 				scsi_version,
306*d5c9a868SElliott Hughes 				data_format,
307*d5c9a868SElliott Hughes 				length,
308*d5c9a868SElliott Hughes 				reserved1[2],
309*d5c9a868SElliott Hughes 				capabilities,
310*d5c9a868SElliott Hughes 				vendor[8],
311*d5c9a868SElliott Hughes 				product[16],
312*d5c9a868SElliott Hughes 				revision[4],
313*d5c9a868SElliott Hughes 				vendor_specific[20],
314*d5c9a868SElliott Hughes 				reserved2[40];
315*d5c9a868SElliott Hughes 		} inq_data;
316*d5c9a868SElliott Hughes 
317*d5c9a868SElliott Hughes 		if (dev->drive != drive)
318*d5c9a868SElliott Hughes 			continue;
319*d5c9a868SElliott Hughes 		expand(dev->name, name);
320*d5c9a868SElliott Hughes 		if ((request & (ZIP_MODE_CHANGE | ZIP_EJECT)) &&
321*d5c9a868SElliott Hughes 		    !(request & ZIP_FORCE) &&
322*d5c9a868SElliott Hughes 		    test_mounted(name)) {
323*d5c9a868SElliott Hughes 			fprintf(stderr,
324*d5c9a868SElliott Hughes 				"Can\'t change status of/eject mounted device\n");
325*d5c9a868SElliott Hughes 			exit(1);
326*d5c9a868SElliott Hughes 		}
327*d5c9a868SElliott Hughes 		precmd(dev);
328*d5c9a868SElliott Hughes 
329*d5c9a868SElliott Hughes 		if(IS_PRIVILEGED(dev))
330*d5c9a868SElliott Hughes 			reclaim_privs();
331*d5c9a868SElliott Hughes 		fd = scsi_open(name, O_RDONLY
332*d5c9a868SElliott Hughes #ifdef O_NDELAY
333*d5c9a868SElliott Hughes 			       | O_NDELAY
334*d5c9a868SElliott Hughes #endif
335*d5c9a868SElliott Hughes 			       , 0644,
336*d5c9a868SElliott Hughes 			       &extra_data);
337*d5c9a868SElliott Hughes 		if(IS_PRIVILEGED(dev))
338*d5c9a868SElliott Hughes 			drop_privs();
339*d5c9a868SElliott Hughes 
340*d5c9a868SElliott Hughes 				/* need readonly, else we can't
341*d5c9a868SElliott Hughes 				 * open the drive on Solaris if
342*d5c9a868SElliott Hughes 				 * write-protected */
343*d5c9a868SElliott Hughes 		if (fd == -1)
344*d5c9a868SElliott Hughes 			continue;
345*d5c9a868SElliott Hughes 		closeExec(fd);
346*d5c9a868SElliott Hughes 
347*d5c9a868SElliott Hughes 		if (!(request & (ZIP_MODE_CHANGE | ZIP_STATUS)))
348*d5c9a868SElliott Hughes 			/* if no mode change or ZIP specific status is
349*d5c9a868SElliott Hughes 			 * involved, the command (eject) is applicable
350*d5c9a868SElliott Hughes 			 * on all drives */
351*d5c9a868SElliott Hughes 			break;
352*d5c9a868SElliott Hughes 
353*d5c9a868SElliott Hughes 		cdb[0] = SCSI_INQUIRY;
354*d5c9a868SElliott Hughes 		cdb[4] = sizeof inq_data;
355*d5c9a868SElliott Hughes 		if (zip_cmd(IS_PRIVILEGED(dev), fd, cdb, 6, SCSI_IO_READ,
356*d5c9a868SElliott Hughes 			    &inq_data, sizeof inq_data, extra_data) != 0) {
357*d5c9a868SElliott Hughes 			close(fd);
358*d5c9a868SElliott Hughes 			continue;
359*d5c9a868SElliott Hughes 		}
360*d5c9a868SElliott Hughes 
361*d5c9a868SElliott Hughes #ifdef DEBUG
362*d5c9a868SElliott Hughes 		fprintf(stderr, "device: %s\n\tvendor: %.8s\n\tproduct: %.16s\n"
363*d5c9a868SElliott Hughes 			"\trevision: %.4s\n", name, inq_data.vendor,
364*d5c9a868SElliott Hughes 			inq_data.product, inq_data.revision);
365*d5c9a868SElliott Hughes #endif /* DEBUG */
366*d5c9a868SElliott Hughes 
367*d5c9a868SElliott Hughes 		if (strncasecmp("IOMEGA  ", inq_data.vendor,
368*d5c9a868SElliott Hughes 				sizeof inq_data.vendor) ||
369*d5c9a868SElliott Hughes 		    (strncasecmp("ZIP 100         ",
370*d5c9a868SElliott Hughes 				 inq_data.product, sizeof inq_data.product) &&
371*d5c9a868SElliott Hughes 		     strncasecmp("ZIP 100 PLUS    ",
372*d5c9a868SElliott Hughes 				 inq_data.product, sizeof inq_data.product) &&
373*d5c9a868SElliott Hughes 		     strncasecmp("ZIP 250         ",
374*d5c9a868SElliott Hughes 				 inq_data.product, sizeof inq_data.product) &&
375*d5c9a868SElliott Hughes 		     strncasecmp("ZIP 750         ",
376*d5c9a868SElliott Hughes 				 inq_data.product, sizeof inq_data.product) &&
377*d5c9a868SElliott Hughes 		     strncasecmp("JAZ 1GB         ",
378*d5c9a868SElliott Hughes 				 inq_data.product, sizeof inq_data.product) &&
379*d5c9a868SElliott Hughes 		     strncasecmp("JAZ 2GB         ",
380*d5c9a868SElliott Hughes 				 inq_data.product, sizeof inq_data.product))) {
381*d5c9a868SElliott Hughes 
382*d5c9a868SElliott Hughes 			/* debugging */
383*d5c9a868SElliott Hughes 			fprintf(stderr,"Skipping drive with vendor='");
384*d5c9a868SElliott Hughes 			fwrite(inq_data.vendor,1, sizeof(inq_data.vendor),
385*d5c9a868SElliott Hughes 			       stderr);
386*d5c9a868SElliott Hughes 			fprintf(stderr,"' product='");
387*d5c9a868SElliott Hughes 			fwrite(inq_data.product,1, sizeof(inq_data.product),
388*d5c9a868SElliott Hughes 			       stderr);
389*d5c9a868SElliott Hughes 			fprintf(stderr,"'\n");
390*d5c9a868SElliott Hughes 			/* end debugging */
391*d5c9a868SElliott Hughes 			close(fd);
392*d5c9a868SElliott Hughes 			continue;
393*d5c9a868SElliott Hughes 		}
394*d5c9a868SElliott Hughes 		break;  /* found Zip/Jaz drive */
395*d5c9a868SElliott Hughes 	}
396*d5c9a868SElliott Hughes 
397*d5c9a868SElliott Hughes 	if (dev->drive == 0) {
398*d5c9a868SElliott Hughes 		fprintf(stderr, "%s: drive '%c:' is not a Zip or Jaz drive\n",
399*d5c9a868SElliott Hughes 			argv[0], drive);
400*d5c9a868SElliott Hughes 		exit(1);
401*d5c9a868SElliott Hughes 	}
402*d5c9a868SElliott Hughes 
403*d5c9a868SElliott Hughes 	if (request & (ZIP_MODE_CHANGE | ZIP_STATUS))
404*d5c9a868SElliott Hughes 		oldMode = get_zip_status(IS_PRIVILEGED(dev), fd, extra_data);
405*d5c9a868SElliott Hughes 
406*d5c9a868SElliott Hughes 	if (request & ZIP_MODE_CHANGE) {
407*d5c9a868SElliott Hughes 				/* request temp unlock, and disk is already unlocked */
408*d5c9a868SElliott Hughes 		if(newMode == ZIP_UNLOCK_TIL_EJECT &&
409*d5c9a868SElliott Hughes 		   (oldMode & ZIP_UNLOCK_TIL_EJECT))
410*d5c9a868SElliott Hughes 			request &= ~ZIP_MODE_CHANGE;
411*d5c9a868SElliott Hughes 
412*d5c9a868SElliott Hughes 				/* no password change requested, and disk is already
413*d5c9a868SElliott Hughes 				 * in the requested state */
414*d5c9a868SElliott Hughes 		if(!(newMode & 0x01) && newMode == oldMode)
415*d5c9a868SElliott Hughes 			request &= ~ZIP_MODE_CHANGE;
416*d5c9a868SElliott Hughes 	}
417*d5c9a868SElliott Hughes 
418*d5c9a868SElliott Hughes 	if (request & ZIP_MODE_CHANGE) {
419*d5c9a868SElliott Hughes 		int ret;
420*d5c9a868SElliott Hughes 		uint8_t unlockMode, unlockMask;
421*d5c9a868SElliott Hughes 		const char *passwd;
422*d5c9a868SElliott Hughes 		char dummy[1];
423*d5c9a868SElliott Hughes 
424*d5c9a868SElliott Hughes 		if(newMode == ZIP_UNLOCK_TIL_EJECT) {
425*d5c9a868SElliott Hughes 			unlockMode = newMode | oldMode;
426*d5c9a868SElliott Hughes 			unlockMask = 9;
427*d5c9a868SElliott Hughes 		} else {
428*d5c9a868SElliott Hughes 			unlockMode = newMode & ~0x5;
429*d5c9a868SElliott Hughes 			unlockMask = 1;
430*d5c9a868SElliott Hughes 		}
431*d5c9a868SElliott Hughes 
432*d5c9a868SElliott Hughes 		if ((oldMode & unlockMask) == 1) {  /* unlock first */
433*d5c9a868SElliott Hughes 			char *s;
434*d5c9a868SElliott Hughes 			passwd = "APlaceForYourStuff";
435*d5c9a868SElliott Hughes 			if ((s = strchr(passwd, '\n'))) *s = '\0';  /* chomp */
436*d5c9a868SElliott Hughes 			iomega_command(IS_PRIVILEGED(dev), fd, unlockMode,
437*d5c9a868SElliott Hughes 				       passwd, extra_data);
438*d5c9a868SElliott Hughes 		}
439*d5c9a868SElliott Hughes 
440*d5c9a868SElliott Hughes 		if ((get_zip_status(IS_PRIVILEGED(dev), fd, extra_data) &
441*d5c9a868SElliott Hughes 		     unlockMask) == 1) {
442*d5c9a868SElliott Hughes 			/* unlock first */
443*d5c9a868SElliott Hughes 			char *s;
444*d5c9a868SElliott Hughes 			passwd = getpass("Password: ");
445*d5c9a868SElliott Hughes 			if ((s = strchr(passwd, '\n'))) *s = '\0';  /* chomp */
446*d5c9a868SElliott Hughes 			if((ret=iomega_command(IS_PRIVILEGED(dev), fd,
447*d5c9a868SElliott Hughes 					       unlockMode, passwd,
448*d5c9a868SElliott Hughes 					       extra_data))){
449*d5c9a868SElliott Hughes 				if (ret == -1) perror("passwd: ");
450*d5c9a868SElliott Hughes 				else fprintf(stderr, "wrong password\n");
451*d5c9a868SElliott Hughes 				exit(1);
452*d5c9a868SElliott Hughes 			}
453*d5c9a868SElliott Hughes 			if((get_zip_status(IS_PRIVILEGED(dev),
454*d5c9a868SElliott Hughes 					   fd, extra_data) &
455*d5c9a868SElliott Hughes 			    unlockMask) == 1) {
456*d5c9a868SElliott Hughes 				fprintf(stderr, "wrong password\n");
457*d5c9a868SElliott Hughes 				exit(1);
458*d5c9a868SElliott Hughes 			}
459*d5c9a868SElliott Hughes 		}
460*d5c9a868SElliott Hughes 
461*d5c9a868SElliott Hughes 		if (newMode & 0x1) {
462*d5c9a868SElliott Hughes 			char first_try[_PASSWORD_LEN+1];
463*d5c9a868SElliott Hughes 
464*d5c9a868SElliott Hughes 			passwd = getpass("Enter new password:");
465*d5c9a868SElliott Hughes 			strncpy(first_try, passwd,_PASSWORD_LEN);
466*d5c9a868SElliott Hughes 			passwd = getpass("Re-type new password:");
467*d5c9a868SElliott Hughes 			if(strncmp(first_try, passwd, _PASSWORD_LEN)) {
468*d5c9a868SElliott Hughes 				fprintf(stderr,
469*d5c9a868SElliott Hughes 					"You misspelled it. Password not set.\n");
470*d5c9a868SElliott Hughes 				exit(1);
471*d5c9a868SElliott Hughes 			}
472*d5c9a868SElliott Hughes 		} else {
473*d5c9a868SElliott Hughes 			passwd = dummy;
474*d5c9a868SElliott Hughes 			dummy[0] = '\0';
475*d5c9a868SElliott Hughes 		}
476*d5c9a868SElliott Hughes 
477*d5c9a868SElliott Hughes 		if(newMode == ZIP_UNLOCK_TIL_EJECT)
478*d5c9a868SElliott Hughes 			newMode |= oldMode;
479*d5c9a868SElliott Hughes 
480*d5c9a868SElliott Hughes 		if((ret=iomega_command(IS_PRIVILEGED(dev), fd,
481*d5c9a868SElliott Hughes 				       newMode, passwd, extra_data))){
482*d5c9a868SElliott Hughes 			if (ret == -1) perror("set passwd: ");
483*d5c9a868SElliott Hughes 			else fprintf(stderr, "password not changed\n");
484*d5c9a868SElliott Hughes 			exit(1);
485*d5c9a868SElliott Hughes 		}
486*d5c9a868SElliott Hughes #ifdef OS_linux
487*d5c9a868SElliott Hughes 		ioctl(fd, BLKRRPART); /* revalidate the disk, so that the
488*d5c9a868SElliott Hughes 					 kernel notices that its writable
489*d5c9a868SElliott Hughes 					 status has changed */
490*d5c9a868SElliott Hughes #endif
491*d5c9a868SElliott Hughes 	}
492*d5c9a868SElliott Hughes 
493*d5c9a868SElliott Hughes 	if (request & ZIP_STATUS) {
494*d5c9a868SElliott Hughes 		const char *unlocked;
495*d5c9a868SElliott Hughes 
496*d5c9a868SElliott Hughes 		if(oldMode & 8)
497*d5c9a868SElliott Hughes 			unlocked = " and unlocked until eject";
498*d5c9a868SElliott Hughes 		else
499*d5c9a868SElliott Hughes 			unlocked = "";
500*d5c9a868SElliott Hughes 		switch (oldMode & ~8) {
501*d5c9a868SElliott Hughes 			case ZIP_RW:
502*d5c9a868SElliott Hughes 				printf("Drive '%c:' is not write-protected\n",
503*d5c9a868SElliott Hughes 				       drive);
504*d5c9a868SElliott Hughes 				break;
505*d5c9a868SElliott Hughes 			case ZIP_RO:
506*d5c9a868SElliott Hughes 				printf("Drive '%c:' is write-protected%s\n",
507*d5c9a868SElliott Hughes 				       drive, unlocked);
508*d5c9a868SElliott Hughes 				break;
509*d5c9a868SElliott Hughes 			case ZIP_RO_PW:
510*d5c9a868SElliott Hughes 				printf("Drive '%c:' is password write-protected%s\n",
511*d5c9a868SElliott Hughes 				       drive, unlocked);
512*d5c9a868SElliott Hughes 				break;
513*d5c9a868SElliott Hughes 			case ZIP_PW:
514*d5c9a868SElliott Hughes 				printf("Drive '%c:' is password protected%s\n",
515*d5c9a868SElliott Hughes 				       drive, unlocked);
516*d5c9a868SElliott Hughes 				break;
517*d5c9a868SElliott Hughes 			default:
518*d5c9a868SElliott Hughes 				printf("Unknown protection mode %d of drive '%c:'\n",
519*d5c9a868SElliott Hughes 				       oldMode, drive);
520*d5c9a868SElliott Hughes 				break;
521*d5c9a868SElliott Hughes 		}
522*d5c9a868SElliott Hughes 	}
523*d5c9a868SElliott Hughes 
524*d5c9a868SElliott Hughes 	if (request & ZIP_EJECT) {
525*d5c9a868SElliott Hughes 		if(request & ZIP_FORCE)
526*d5c9a868SElliott Hughes 			if(door_command(IS_PRIVILEGED(dev), fd,
527*d5c9a868SElliott Hughes 					SCSI_ALLOW_MEDIUM_REMOVAL, 0,
528*d5c9a868SElliott Hughes 					extra_data) < 0) {
529*d5c9a868SElliott Hughes 				perror("door unlock: ");
530*d5c9a868SElliott Hughes 				exit(1);
531*d5c9a868SElliott Hughes 			}
532*d5c9a868SElliott Hughes 
533*d5c9a868SElliott Hughes 		if(door_command(IS_PRIVILEGED(dev), fd,
534*d5c9a868SElliott Hughes 				SCSI_START_STOP, 1,
535*d5c9a868SElliott Hughes 				extra_data) < 0) {
536*d5c9a868SElliott Hughes 			perror("stop motor: ");
537*d5c9a868SElliott Hughes 			exit(1);
538*d5c9a868SElliott Hughes 		}
539*d5c9a868SElliott Hughes 
540*d5c9a868SElliott Hughes 		if(door_command(IS_PRIVILEGED(dev), fd,
541*d5c9a868SElliott Hughes 				SCSI_START_STOP, 2, extra_data) < 0) {
542*d5c9a868SElliott Hughes 			perror("eject: ");
543*d5c9a868SElliott Hughes 			exit(1);
544*d5c9a868SElliott Hughes 		}
545*d5c9a868SElliott Hughes 		if(door_command(IS_PRIVILEGED(dev), fd,
546*d5c9a868SElliott Hughes 				SCSI_START_STOP, 2, extra_data) < 0) {
547*d5c9a868SElliott Hughes 			perror("second eject: ");
548*d5c9a868SElliott Hughes 			exit(1);
549*d5c9a868SElliott Hughes 		}
550*d5c9a868SElliott Hughes 	}
551*d5c9a868SElliott Hughes 
552*d5c9a868SElliott Hughes 	close(fd);
553*d5c9a868SElliott Hughes 	exit(0);
554*d5c9a868SElliott Hughes }
555