1*39bbc68aSsevan /* $NetBSD: eject.c,v 1.28 2016/09/05 00:40:28 sevan Exp $ */
2a651e1a0Stron
3a651e1a0Stron /*-
4a651e1a0Stron * Copyright (c) 1999 The NetBSD Foundation, Inc.
5a651e1a0Stron * All rights reserved.
6a651e1a0Stron *
7a651e1a0Stron * This code is derived from software contributed to The NetBSD Foundation
8a651e1a0Stron * by Chris Jones.
9764fa4b6Spk *
10764fa4b6Spk * Redistribution and use in source and binary forms, with or without
11764fa4b6Spk * modification, are permitted provided that the following conditions
12764fa4b6Spk * are met:
13764fa4b6Spk * 1. Redistributions of source code must retain the above copyright
14764fa4b6Spk * notice, this list of conditions and the following disclaimer.
15764fa4b6Spk * 2. Redistributions in binary form must reproduce the above copyright
16764fa4b6Spk * notice, this list of conditions and the following disclaimer in the
17764fa4b6Spk * documentation and/or other materials provided with the distribution.
18764fa4b6Spk *
19a651e1a0Stron * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20a651e1a0Stron * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21a651e1a0Stron * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22a651e1a0Stron * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23a651e1a0Stron * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24a651e1a0Stron * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25a651e1a0Stron * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26a651e1a0Stron * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27a651e1a0Stron * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28a651e1a0Stron * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29a651e1a0Stron * POSSIBILITY OF SUCH DAMAGE.
30764fa4b6Spk */
31764fa4b6Spk
32a651e1a0Stron #include <sys/cdefs.h>
33a651e1a0Stron #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1999\
3598e5374cSlukem The NetBSD Foundation, Inc. All rights reserved.");
3603cb143eScjs #endif /* not lint */
3703cb143eScjs
3803cb143eScjs #ifndef lint
39*39bbc68aSsevan __RCSID("$NetBSD: eject.c,v 1.28 2016/09/05 00:40:28 sevan Exp $");
4003cb143eScjs #endif /* not lint */
41a651e1a0Stron
42d78020d1Sad #include <sys/types.h>
43d78020d1Sad #include <sys/cdio.h>
44d78020d1Sad #include <sys/disklabel.h>
45d78020d1Sad #include <sys/ioctl.h>
46d78020d1Sad #include <sys/param.h>
47d78020d1Sad #include <sys/ucred.h>
48d78020d1Sad #include <sys/mount.h>
49d78020d1Sad #include <sys/mtio.h>
50d78020d1Sad
51a651e1a0Stron #include <ctype.h>
52a651e1a0Stron #include <err.h>
53a651e1a0Stron #include <fcntl.h>
54a651e1a0Stron #include <stdio.h>
55a651e1a0Stron #include <stdlib.h>
56a651e1a0Stron #include <string.h>
57a651e1a0Stron #include <unistd.h>
58d78020d1Sad #include <util.h>
59a651e1a0Stron
6052f56a8cSchristos #ifdef AMD_SUPPORT
6152f56a8cSchristos # include "am_glue.h"
6252f56a8cSchristos #endif
6352f56a8cSchristos
64a651e1a0Stron struct nicknames_s {
65a127d189Schristos const char *name; /* The name given on the command line. */
66a127d189Schristos const char *devname; /* The base name of the device */
67ccb8f4d3Sbjh21 int type; /* The type of device, for determining what
68ccb8f4d3Sbjh21 * ioctl to use. */
69a651e1a0Stron # define TAPE 0x10
70a651e1a0Stron # define DISK 0x20
71a651e1a0Stron /* OR one of the above with one of the below: */
72a651e1a0Stron # define NOTLOADABLE 0x00
73a651e1a0Stron # define LOADABLE 0x01
74f3751075Sxtraeme # define FLOPPY 0x2
75a651e1a0Stron # define TYPEMASK ((int)~0x01)
76a651e1a0Stron } nicknames[] = {
77f3751075Sxtraeme { "diskette", "fd", DISK | FLOPPY | NOTLOADABLE },
78f3751075Sxtraeme { "floppy", "fd", DISK | FLOPPY | NOTLOADABLE },
79f3751075Sxtraeme { "fd", "fd", DISK | FLOPPY | NOTLOADABLE },
803dcf0c67Sbouyer { "sd", "sd", DISK | NOTLOADABLE },
8180f0af1aSbouyer { "cdrom", "cd", DISK | LOADABLE },
8280f0af1aSbouyer { "cd", "cd", DISK | LOADABLE },
832a4ad09fSabs { "racd", "racd", DISK | LOADABLE },
843c317264Smycroft { "cdr", "cd", DISK | LOADABLE },
853c317264Smycroft { "cdrw", "cd", DISK | LOADABLE },
863c317264Smycroft { "dvdrom", "cd", DISK | LOADABLE },
873c317264Smycroft { "dvd", "cd", DISK | LOADABLE },
883c317264Smycroft { "dvdr", "cd", DISK | LOADABLE },
893c317264Smycroft { "dvdrw", "cd", DISK | LOADABLE },
9080f0af1aSbouyer { "mcd", "mcd", DISK | LOADABLE }, /* XXX Is this true? */
91a651e1a0Stron { "tape", "st", TAPE | NOTLOADABLE },
92a651e1a0Stron { "st", "st", TAPE | NOTLOADABLE },
93a651e1a0Stron { "dat", "st", TAPE | NOTLOADABLE },
94a127d189Schristos { "exabyte", "st", TAPE | NOTLOADABLE }
95a651e1a0Stron };
96ccb8f4d3Sbjh21 #define MAXNICKLEN 12 /* at least enough room for the longest
97ccb8f4d3Sbjh21 * nickname */
98a651e1a0Stron #define MAXDEVLEN (MAXNICKLEN + 7) /* "/dev/r" ... "a" */
99a651e1a0Stron
100a651e1a0Stron struct devtypes_s {
101a127d189Schristos const char *name;
102a651e1a0Stron int type;
103a651e1a0Stron } devtypes[] = {
104a651e1a0Stron { "diskette", DISK | NOTLOADABLE },
105a651e1a0Stron { "floppy", DISK | NOTLOADABLE },
10680f0af1aSbouyer { "cdrom", DISK | LOADABLE },
107a651e1a0Stron { "disk", DISK | NOTLOADABLE },
108a127d189Schristos { "tape", TAPE | NOTLOADABLE }
109a651e1a0Stron };
110a651e1a0Stron
11179931f7bSbjh21 enum eject_op {
11279931f7bSbjh21 OP_EJECT, OP_LOAD, OP_LOCK, OP_UNLOCK
11379931f7bSbjh21 };
11479931f7bSbjh21
115a651e1a0Stron int verbose_f = 0;
116a651e1a0Stron int umount_f = 1;
117a651e1a0Stron
118a127d189Schristos __dead static void usage(void);
119a127d189Schristos static char *nick2dev(const char *);
120a127d189Schristos static char *nick2rdev(const char *);
121a127d189Schristos static int guess_devtype(const char *);
122a127d189Schristos static void eject_disk(const char *, enum eject_op);
123a127d189Schristos static void eject_tape(const char *, enum eject_op);
124a127d189Schristos static void unmount_dev(const char *);
125a651e1a0Stron
126a651e1a0Stron int
main(int argc,char * argv[])127ccb8f4d3Sbjh21 main(int argc, char *argv[])
128a651e1a0Stron {
129a651e1a0Stron int ch;
130a127d189Schristos int devtype;
131c402ba6fSlukem size_t n;
132a127d189Schristos char *dev_name; /* XXX - devname is declared in stdlib.h */
133a127d189Schristos enum eject_op op;
134a127d189Schristos
135a127d189Schristos devtype = -1;
136a127d189Schristos dev_name = NULL;
137a127d189Schristos op = OP_EJECT;
138764fa4b6Spk
13979931f7bSbjh21 while ((ch = getopt(argc, argv, "d:flLnt:Uv")) != -1) {
140764fa4b6Spk switch (ch) {
141764fa4b6Spk case 'd':
142a127d189Schristos dev_name = optarg;
143764fa4b6Spk break;
144764fa4b6Spk case 'f':
145a651e1a0Stron umount_f = 0;
146764fa4b6Spk break;
147425c9945Sbouyer case 'l':
14879931f7bSbjh21 if (op != OP_EJECT)
14979931f7bSbjh21 usage();
15079931f7bSbjh21 op = OP_LOAD;
15179931f7bSbjh21 break;
15279931f7bSbjh21 case 'L':
15379931f7bSbjh21 if (op != OP_EJECT)
15479931f7bSbjh21 usage();
15579931f7bSbjh21 op = OP_LOCK;
156425c9945Sbouyer break;
157764fa4b6Spk case 'n':
158a127d189Schristos for (n = 0; n < __arraycount(nicknames); n++) {
159a651e1a0Stron struct nicknames_s *np = &nicknames[n];
160a651e1a0Stron
161a127d189Schristos (void)printf("%s -> %s\n",
162a127d189Schristos np->name, nick2dev(np->name));
1637b5f411eSmsaitoh }
164a127d189Schristos return 0;
165764fa4b6Spk case 't':
166c402ba6fSlukem for (n = 0; n < __arraycount(devtypes); n++) {
167c402ba6fSlukem if (strcasecmp(devtypes[n].name, optarg)
168a127d189Schristos == 0) {
169c402ba6fSlukem devtype = devtypes[n].type;
170764fa4b6Spk break;
171764fa4b6Spk }
172764fa4b6Spk }
173ccb8f4d3Sbjh21 if (devtype == -1)
17479931f7bSbjh21 errx(1, "%s: unknown device type", optarg);
17579931f7bSbjh21 break;
17679931f7bSbjh21 case 'U':
17779931f7bSbjh21 if (op != OP_EJECT)
17879931f7bSbjh21 usage();
17979931f7bSbjh21 op = OP_UNLOCK;
180764fa4b6Spk break;
181764fa4b6Spk case 'v':
182a651e1a0Stron verbose_f = 1;
183764fa4b6Spk break;
184764fa4b6Spk default:
185764fa4b6Spk usage();
186764fa4b6Spk /* NOTREACHED */
187764fa4b6Spk }
188764fa4b6Spk }
189764fa4b6Spk argc -= optind;
190764fa4b6Spk argv += optind;
191764fa4b6Spk
192a127d189Schristos if (dev_name == NULL) {
193a127d189Schristos if (argc == 0)
194a651e1a0Stron usage();
195a127d189Schristos else
196a127d189Schristos dev_name = argv[0];
197764fa4b6Spk }
198ccb8f4d3Sbjh21 if (devtype == -1)
199a127d189Schristos devtype = guess_devtype(dev_name);
200ccb8f4d3Sbjh21 if (devtype == -1)
201a127d189Schristos errx(1, "%s: unable to determine type of device", dev_name);
202a651e1a0Stron if (verbose_f) {
203a127d189Schristos (void)printf("device type == ");
204a651e1a0Stron if ((devtype & TYPEMASK) == TAPE)
205a127d189Schristos (void)printf("tape\n");
206a651e1a0Stron else
207a127d189Schristos (void)printf("disk, floppy, or cdrom\n");
208a651e1a0Stron }
209a651e1a0Stron if (umount_f)
210a127d189Schristos unmount_dev(dev_name);
211a651e1a0Stron
21280f0af1aSbouyer /* XXX Tapes and disks have different ioctl's: */
213a651e1a0Stron if ((devtype & TYPEMASK) == TAPE)
214a127d189Schristos eject_tape(dev_name, op);
215a651e1a0Stron else
216a127d189Schristos eject_disk(dev_name, op);
217a651e1a0Stron
218a651e1a0Stron if (verbose_f)
219a127d189Schristos (void)printf("done.\n");
220a651e1a0Stron
221a127d189Schristos return 0;
222a651e1a0Stron }
223a651e1a0Stron
224a127d189Schristos __dead
225a127d189Schristos static void
usage(void)226a651e1a0Stron usage(void)
227a651e1a0Stron {
228ccb8f4d3Sbjh21
229a127d189Schristos (void)fprintf(stderr, "usage: eject [-fv] [-l | -L | -U] "
23079931f7bSbjh21 "[-t device-type] [-d] device\n");
231a127d189Schristos (void)fprintf(stderr, " eject -n\n");
23279931f7bSbjh21 exit(1);
233a651e1a0Stron }
234a651e1a0Stron
235a127d189Schristos static int
guess_devtype(const char * dev_name)236a127d189Schristos guess_devtype(const char *dev_name)
237a651e1a0Stron {
238c402ba6fSlukem size_t n;
239a651e1a0Stron
240a651e1a0Stron /* Nickname match: */
241a127d189Schristos for (n = 0; n < __arraycount(nicknames); n++) {
242a127d189Schristos if (strncasecmp(nicknames[n].name, dev_name,
243a651e1a0Stron strlen(nicknames[n].name)) == 0)
244a127d189Schristos return nicknames[n].type;
245a651e1a0Stron }
246a651e1a0Stron
247a651e1a0Stron /*
248a127d189Schristos * If we still don't know it, then try to compare vs. dev and
249a127d189Schristos * rdev names that we know.
250a651e1a0Stron */
251a651e1a0Stron /* dev first: */
252a127d189Schristos for (n = 0; n < __arraycount(nicknames); n++) {
253a651e1a0Stron char *name;
254a651e1a0Stron name = nick2dev(nicknames[n].name);
255a651e1a0Stron /*
256a127d189Schristos * Assume that the part of the name that distinguishes
257a127d189Schristos * the instance of this device begins with a 0.
258a651e1a0Stron */
259a651e1a0Stron *(strchr(name, '0')) = '\0';
260a127d189Schristos if (strncmp(name, dev_name, strlen(name)) == 0)
261a127d189Schristos return nicknames[n].type;
262a651e1a0Stron }
263a651e1a0Stron
264a651e1a0Stron /* Now rdev: */
265a127d189Schristos for (n = 0; n < __arraycount(nicknames); n++) {
266a651e1a0Stron char *name = nick2rdev(nicknames[n].name);
267a651e1a0Stron *(strchr(name, '0')) = '\0';
268a127d189Schristos if (strncmp(name, dev_name, strlen(name)) == 0)
269a127d189Schristos return nicknames[n].type;
270a651e1a0Stron }
271a651e1a0Stron
272a651e1a0Stron /* Not found. */
273a127d189Schristos return -1;
274a651e1a0Stron }
275a127d189Schristos
276a651e1a0Stron /* "floppy5" -> "/dev/fd5a". Yep, this uses a static buffer. */
277a127d189Schristos static char *
nick2dev(const char * nn)278a127d189Schristos nick2dev(const char *nn)
279a651e1a0Stron {
280a127d189Schristos static char dev_name[MAXDEVLEN];
281c402ba6fSlukem size_t n;
282a127d189Schristos int devnum;
283a651e1a0Stron
284a127d189Schristos devnum = 0;
285a127d189Schristos for (n = 0; n < __arraycount(nicknames); n++) {
286a651e1a0Stron if (strncasecmp(nicknames[n].name, nn,
287a651e1a0Stron strlen(nicknames[n].name)) == 0) {
288a127d189Schristos (void)sscanf(nn, "%*[^0-9]%d", &devnum);
289a127d189Schristos (void)sprintf(dev_name, "/dev/%s%d",
290a127d189Schristos nicknames[n].devname, devnum);
291a651e1a0Stron if ((nicknames[n].type & TYPEMASK) != TAPE)
292a127d189Schristos (void)strcat(dev_name, "a");
293a127d189Schristos return dev_name;
294a651e1a0Stron }
295a651e1a0Stron }
296a127d189Schristos return NULL;
297a127d189Schristos }
298a651e1a0Stron
299a651e1a0Stron /* "floppy5" -> "/dev/rfd5c". Static buffer. */
300a127d189Schristos static char *
nick2rdev(const char * nn)301a127d189Schristos nick2rdev(const char *nn)
302a651e1a0Stron {
303a127d189Schristos static char dev_name[MAXDEVLEN];
304c402ba6fSlukem size_t n;
305a127d189Schristos int devnum;
306a651e1a0Stron
307a127d189Schristos devnum = 0;
308a127d189Schristos for (n = 0; n < __arraycount(nicknames); n++) {
309a651e1a0Stron if (strncasecmp(nicknames[n].name, nn,
310a651e1a0Stron strlen(nicknames[n].name)) == 0) {
311a127d189Schristos (void)sscanf(nn, "%*[^0-9]%d", &devnum);
312a127d189Schristos (void)sprintf(dev_name, "/dev/r%s%d",
313a127d189Schristos nicknames[n].devname, devnum);
314a651e1a0Stron if ((nicknames[n].type & TYPEMASK) != TAPE) {
315a127d189Schristos (void)strcat(dev_name, "a");
316f3751075Sxtraeme if ((nicknames[n].type & FLOPPY) != FLOPPY)
317a127d189Schristos dev_name[strlen(dev_name) - 1]
318a127d189Schristos += getrawpartition();
319a651e1a0Stron }
320a127d189Schristos return dev_name;
321a651e1a0Stron }
322a651e1a0Stron }
323a127d189Schristos return NULL;
324a127d189Schristos }
325a651e1a0Stron
326a651e1a0Stron /* Unmount all filesystems attached to dev. */
327a127d189Schristos static void
unmount_dev(const char * name)328a127d189Schristos unmount_dev(const char *name)
329a651e1a0Stron {
3306bd1d6d4Schristos struct statvfs *mounts;
331a127d189Schristos size_t len;
332a127d189Schristos int i, nmnts;
333a127d189Schristos const char *dn;
334a651e1a0Stron
335a651e1a0Stron nmnts = getmntinfo(&mounts, MNT_NOWAIT);
336a127d189Schristos if (nmnts == 0)
337a651e1a0Stron err(1, "getmntinfo");
338a127d189Schristos
339a651e1a0Stron /* Make sure we have a device name: */
340a651e1a0Stron dn = nick2dev(name);
341a651e1a0Stron if (dn == NULL)
342a651e1a0Stron dn = name;
343a651e1a0Stron
344a651e1a0Stron /* Set len to strip off the partition name: */
345a651e1a0Stron len = strlen(dn);
34643371ff1Sdsl if (!isdigit((unsigned char)dn[len - 1]))
347a651e1a0Stron len--;
348a127d189Schristos if (!isdigit((unsigned char)dn[len - 1]))
349a651e1a0Stron errx(1, "Can't figure out base name for dev name %s", dn);
350a127d189Schristos
351a651e1a0Stron for (i = 0; i < nmnts; i++) {
352a651e1a0Stron if (strncmp(mounts[i].f_mntfromname, dn, len) == 0) {
353a651e1a0Stron if (verbose_f)
354a127d189Schristos (void)printf("Unmounting %s from %s...\n",
355a651e1a0Stron mounts[i].f_mntfromname,
356a651e1a0Stron mounts[i].f_mntonname);
357a651e1a0Stron
35852f56a8cSchristos if (
35952f56a8cSchristos #ifdef AMD_SUPPORT
36052f56a8cSchristos am_unmount(mounts[i].f_mntonname) != 0 &&
36152f56a8cSchristos #endif
36252f56a8cSchristos unmount(mounts[i].f_mntonname, 0) == -1)
363a651e1a0Stron err(1, "unmount: %s", mounts[i].f_mntonname);
364a651e1a0Stron }
365a651e1a0Stron }
366a651e1a0Stron return;
367a651e1a0Stron }
368a651e1a0Stron
369a127d189Schristos static void
eject_tape(const char * name,enum eject_op op)370a127d189Schristos eject_tape(const char *name, enum eject_op op)
371a651e1a0Stron {
372a651e1a0Stron struct mtop m;
373a651e1a0Stron int fd;
374a127d189Schristos const char *dn;
375a651e1a0Stron
376a651e1a0Stron dn = nick2rdev(name);
377ccb8f4d3Sbjh21 if (dn == NULL)
378a651e1a0Stron dn = name; /* Hope for the best. */
379a651e1a0Stron fd = open(dn, O_RDONLY);
380ccb8f4d3Sbjh21 if (fd == -1)
381a651e1a0Stron err(1, "open: %s", dn);
38279931f7bSbjh21 switch (op) {
38379931f7bSbjh21 case OP_EJECT:
384a651e1a0Stron if (verbose_f)
385a127d189Schristos (void)printf("Ejecting %s...\n", dn);
386a651e1a0Stron
387a651e1a0Stron m.mt_op = MTOFFL;
388a651e1a0Stron m.mt_count = 0;
389ccb8f4d3Sbjh21 if (ioctl(fd, MTIOCTOP, &m) == -1)
390a651e1a0Stron err(1, "ioctl: MTIOCTOP: %s", dn);
39179931f7bSbjh21 break;
39279931f7bSbjh21 case OP_LOAD:
39379931f7bSbjh21 errx(1, "cannot load tapes");
39479931f7bSbjh21 /* NOTREACHED */
39579931f7bSbjh21 case OP_LOCK:
39679931f7bSbjh21 errx(1, "cannot lock tapes");
39779931f7bSbjh21 /* NOTREACHED */
39879931f7bSbjh21 case OP_UNLOCK:
39979931f7bSbjh21 errx(1, "cannot unlock tapes");
40079931f7bSbjh21 /* NOTREACHED */
40179931f7bSbjh21 }
402a127d189Schristos (void)close(fd);
403a651e1a0Stron return;
404a651e1a0Stron }
405a651e1a0Stron
406a127d189Schristos static void
eject_disk(const char * name,enum eject_op op)407a127d189Schristos eject_disk(const char *name, enum eject_op op)
408a651e1a0Stron {
409a651e1a0Stron int fd;
410a127d189Schristos const char *dn;
411a651e1a0Stron int arg;
412a651e1a0Stron
413a651e1a0Stron dn = nick2rdev(name);
414ccb8f4d3Sbjh21 if (dn == NULL)
415a651e1a0Stron dn = name; /* Hope for the best. */
416a651e1a0Stron fd = open(dn, O_RDONLY);
417ccb8f4d3Sbjh21 if (fd == -1)
418a651e1a0Stron err(1, "open: %s", dn);
41979931f7bSbjh21 switch (op) {
42079931f7bSbjh21 case OP_LOAD:
421a651e1a0Stron if (verbose_f)
422a127d189Schristos (void)printf("Closing %s...\n", dn);
423a651e1a0Stron
424ccb8f4d3Sbjh21 if (ioctl(fd, CDIOCCLOSE, NULL) == -1)
425a651e1a0Stron err(1, "ioctl: CDIOCCLOSE: %s", dn);
42679931f7bSbjh21 break;
42779931f7bSbjh21 case OP_EJECT:
428a651e1a0Stron if (verbose_f)
429a127d189Schristos (void)printf("Ejecting %s...\n", dn);
430a651e1a0Stron
431a651e1a0Stron arg = 0;
43280f0af1aSbouyer if (umount_f == 0) {
43380f0af1aSbouyer /* force eject, unlock the device first */
43480f0af1aSbouyer if (ioctl(fd, DIOCLOCK, &arg) == -1)
43579931f7bSbjh21 err(1, "ioctl: DIOCLOCK: %s", dn);
43680f0af1aSbouyer arg = 1;
43780f0af1aSbouyer }
438a651e1a0Stron if (ioctl(fd, DIOCEJECT, &arg) == -1)
439a651e1a0Stron err(1, "ioctl: DIOCEJECT: %s", dn);
44079931f7bSbjh21 break;
44179931f7bSbjh21 case OP_LOCK:
44279931f7bSbjh21 if (verbose_f)
443a127d189Schristos (void)printf("Locking %s...\n", dn);
44479931f7bSbjh21
44579931f7bSbjh21 arg = 1;
44679931f7bSbjh21 if (ioctl(fd, DIOCLOCK, &arg) == -1)
44779931f7bSbjh21 err(1, "ioctl: DIOCLOCK: %s", dn);
44879931f7bSbjh21 break;
44979931f7bSbjh21 case OP_UNLOCK:
45079931f7bSbjh21 if (verbose_f)
451a127d189Schristos (void)printf("Unlocking %s...\n", dn);
45279931f7bSbjh21
45379931f7bSbjh21 arg = 0;
45479931f7bSbjh21 if (ioctl(fd, DIOCLOCK, &arg) == -1)
45579931f7bSbjh21 err(1, "ioctl: DIOCLOCK: %s", dn);
45679931f7bSbjh21 break;
457764fa4b6Spk }
458764fa4b6Spk
459a127d189Schristos (void)close(fd);
460a651e1a0Stron return;
461764fa4b6Spk }
462