1 /*
2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998, 2001 University of Maryland at College Park
4 * Copyright (c) 2007-2013 Zmanda, Inc. All Rights Reserved.
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
16 *
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
26 */
27 /*
28 * $Id: getfsent.c,v 1.38 2006/07/19 17:41:14 martinea Exp $
29 *
30 * generic version of code to read fstab
31 */
32
33 #include "amanda.h"
34 #include "util.h"
35
36 #ifdef TEST
37 # include <stdio.h>
38 # include <sys/types.h>
39 #endif
40
41 #include "getfsent.h"
42
43 static char *dev2rdev(char *);
44
45 /*
46 * You are in a twisty maze of passages, all alike.
47 * Geesh.
48 */
49
50 #if defined(HAVE_FSTAB_H) && !defined(HAVE_MNTENT_H) /* { */
51 /*
52 ** BSD (GETFSENT_BSD)
53 */
54 #define GETFSENT_TYPE "BSD (Ultrix, AIX)"
55
56 #include <fstab.h>
57
58 int
open_fstab(void)59 open_fstab(void)
60 {
61 return setfsent();
62 }
63
64 void
close_fstab(void)65 close_fstab(void)
66 {
67 endfsent();
68 }
69
70
71 int
get_fstab_nextentry(generic_fsent_t * fsent)72 get_fstab_nextentry(
73 generic_fsent_t * fsent)
74 {
75 struct fstab *sys_fsent = getfsent();
76 static char *xfsname = NULL, *xmntdir = NULL;
77 static char *xfstype = NULL, *xmntopts = NULL;
78
79 if(!sys_fsent)
80 return 0;
81 fsent->fsname = xfsname = newstralloc(xfsname, sys_fsent->fs_spec);
82 fsent->mntdir = xmntdir = newstralloc(xmntdir, sys_fsent->fs_file);
83 fsent->freq = sys_fsent->fs_freq;
84 fsent->passno = sys_fsent->fs_passno;
85 #ifdef STATFS_ULTRIX
86 fsent->fstype = xfstype = newstralloc(xfstype, sys_fsent->fs_name);
87 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_opts);
88 #else
89 #if defined(_AIX)
90 fsent->fstype = xfstype = newstralloc(xfstype, _("unknown"));
91 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_type);
92 #else
93 fsent->fstype = xfstype = newstralloc(xfstype, sys_fsent->fs_vfstype);
94 fsent->mntopts = xmntopts = newstralloc(xmntopts, sys_fsent->fs_mntops);
95 #endif
96 #endif
97 return 1;
98 }
99
100 #else
101 #if defined(HAVE_SYS_VFSTAB_H) /* } { */
102 /*
103 ** SVR4 (GETFSENT_SOLARIS)
104 */
105 #define GETFSENT_TYPE "SVR4 (Solaris)"
106
107 #include <sys/vfstab.h>
108
109 static FILE *fstabf = NULL;
110
111 int
open_fstab(void)112 open_fstab(void)
113 {
114 close_fstab();
115 return (fstabf = fopen(VFSTAB, "r")) != NULL;
116 }
117
118 void
close_fstab(void)119 close_fstab(void)
120 {
121 if(fstabf)
122 afclose(fstabf);
123 fstabf = NULL;
124 }
125
126 int
get_fstab_nextentry(generic_fsent_t * fsent)127 get_fstab_nextentry(
128 generic_fsent_t * fsent)
129 {
130 struct vfstab sys_fsent;
131
132 memset(&sys_fsent, 0, SIZEOF(sys_fsent));
133 if(getvfsent(fstabf, &sys_fsent) != 0)
134 return 0;
135
136 fsent->fsname = sys_fsent.vfs_special;
137 fsent->fstype = sys_fsent.vfs_fstype;
138 fsent->mntdir = sys_fsent.vfs_mountp;
139 fsent->mntopts = sys_fsent.vfs_mntopts;
140 fsent->freq = 1; /* N/A */
141 fsent->passno = sys_fsent.vfs_fsckpass? atoi(sys_fsent.vfs_fsckpass) : 0;
142 return 1;
143 }
144
145 #else
146 # if defined(HAVE_MNTENT_H) /* } { */
147
148 /*
149 ** System V.3 (GETFSENT_SVR3, GETFSENT_LINUX)
150 */
151 #define GETFSENT_TYPE "SVR3 (NeXTstep, Irix, Linux, HP-UX)"
152
153 #include <mntent.h>
154
155 #if defined(HAVE_ENDMNTENT)
156 #define AMCLOSE_MNTENT(x) endmntent(x)
157 #else
158 #define AMCLOSE_MNTENT(x) fclose(x)
159 #endif
160
161 static FILE *fstabf1 = NULL; /* /proc/mounts */
162 static FILE *fstabf2 = NULL; /* MOUNTED */
163 static FILE *fstabf3 = NULL; /* MNTTAB */
164
165 int
open_fstab(void)166 open_fstab(void)
167 {
168 close_fstab();
169 #if defined(HAVE_SETMNTENT)
170 fstabf1 = setmntent("/proc/mounts", "r");
171 # if defined(MOUNTED)
172 fstabf2 = setmntent(MOUNTED, "r");
173 # endif
174 # if defined(MNTTAB)
175 fstabf3 = setmntent(MNTTAB, "r");
176 # endif
177 #else
178 # if defined(MNTTAB)
179 fstabf3 = fopen(MNTTAB, "r");
180 # endif
181 #endif
182 return (fstabf1 != NULL || fstabf2 != NULL || fstabf3 != NULL);
183 }
184
185 void
close_fstab(void)186 close_fstab(void)
187 {
188 if (fstabf1) {
189 AMCLOSE_MNTENT(fstabf1);
190 fstabf1 = NULL;
191 }
192 if (fstabf2) {
193 AMCLOSE_MNTENT(fstabf2);
194 fstabf2 = NULL;
195 }
196 if (fstabf3) {
197 AMCLOSE_MNTENT(fstabf3);
198 fstabf3 = NULL;
199 }
200 }
201
202 int
get_fstab_nextentry(generic_fsent_t * fsent)203 get_fstab_nextentry(
204 generic_fsent_t * fsent)
205 {
206 struct mntent *sys_fsent = NULL;
207
208 if(fstabf1) {
209 sys_fsent = getmntent(fstabf1);
210 if(!sys_fsent) {
211 AMCLOSE_MNTENT(fstabf1);
212 fstabf1 = NULL;
213 }
214 }
215 if(!sys_fsent && fstabf2) {
216 sys_fsent = getmntent(fstabf2);
217 if(!sys_fsent) {
218 AMCLOSE_MNTENT(fstabf2);
219 fstabf2 = NULL;
220 }
221 }
222 if(!sys_fsent && fstabf3) {
223 sys_fsent = getmntent(fstabf3);
224 if(!sys_fsent) {
225 AMCLOSE_MNTENT(fstabf3);
226 fstabf3 = NULL;
227 }
228 }
229 if(!sys_fsent) {
230 return 0;
231 }
232
233 fsent->fsname = sys_fsent->mnt_fsname;
234 fsent->fstype = sys_fsent->mnt_type;
235 fsent->mntdir = sys_fsent->mnt_dir;
236 fsent->mntopts = sys_fsent->mnt_opts;
237 fsent->freq = sys_fsent->mnt_freq;
238 fsent->passno = sys_fsent->mnt_passno;
239 return 1;
240 }
241
242 # else
243 # if defined(HAVE_SYS_MNTTAB_H) || defined(STATFS_SCO_OS5) /* } { */
244
245 /* we won't actually include mnttab.h, since it contains nothing useful.. */
246
247 #define GETFSENT_TYPE "SVR3 (Interactive UNIX)"
248
249 #include <stdio.h>
250 #include <string.h>
251 #include <ctype.h>
252
253 #define FSTAB "/etc/fstab"
254
255 static FILE *fstabf = NULL;
256
257 int
open_fstab(void)258 open_fstab(void)
259 {
260 close_fstab();
261 return (fstabf = fopen(FSTAB, "r")) != NULL;
262 }
263
264 void
close_fstab(void)265 close_fstab(void)
266 {
267 if(fstabf)
268 afclose(fstabf);
269 fstabf = NULL;
270 }
271
272 static generic_fsent_t _fsent;
273
274 int
get_fstab_nextentry(generic_fsent_t * fsent)275 get_fstab_nextentry(
276 generic_fsent_t * fsent)
277 {
278 static char *lfsnam = NULL;
279 static char *opts = NULL;
280 static char *cp = NULL;
281 char *s;
282 int ch;
283
284 amfree(cp);
285 for (; (cp = agets(fstabf)) != NULL; free(cp)) {
286 if (cp[0] == '\0')
287 continue;
288 fsent->fsname = strtok(cp, " \t");
289 if ( fsent->fsname && *fsent->fsname != '#' )
290 break;
291 }
292 if (cp == NULL) return 0;
293
294 fsent->mntdir = strtok((char *)NULL, " \t");
295 fsent->mntopts = strtok((char *)NULL, " \t");
296 if ( *fsent->mntopts != '-' ) {
297 fsent->fstype = fsent->mntopts;
298 fsent->mntopts = "rw";
299 } else {
300 fsent->fstype = "";
301 if (strcmp(fsent->mntopts, "-r") == 0) {
302 fsent->mntopts = "ro";
303 }
304 }
305 if ((s = strchr(fsent->fstype, ',')) != NULL) {
306 *s++ = '\0';
307 strappend(fsent->mntopts, ",");
308 strappend(fsent->mntopts, s);
309 }
310
311 lfsnam = newstralloc(lfsnam, fsent->fstype);
312 s = lfsnam;
313 while((ch = *s++) != '\0') {
314 if(isupper(ch)) ch = tolower(ch);
315 s[-1] = ch;
316 }
317 fsent->fstype = lfsnam;
318
319 if (strncmp_const(fsent->fstype, "hs") == 0)
320 fsent->fstype = "iso9660";
321
322 fsent->freq = 0;
323 fsent->passno = 0;
324
325 return 1;
326 }
327
328 # else
329 # if defined(HAVE_MNTTAB_H) /* } { */
330
331 #define GETFSENT_TYPE "SVR3 (SCO UNIX)"
332
333 #include <mnttab.h>
334 #include <sys/fstyp.h>
335 #include <sys/statfs.h>
336
337 #define MNTTAB "/etc/mnttab"
338
339 /*
340 * If these are defined somewhere please let me know.
341 */
342
343 #define MNT_READONLY 0101
344 #define MNT_READWRITE 0100
345
346 static FILE *fstabf = NULL;
347
348 int
open_fstab(void)349 open_fstab(void)
350 {
351 close_fstab();
352 return (fstabf = fopen(MNTTAB, "r")) != NULL;
353 }
354
355 void
close_fstab(void)356 close_fstab(void)
357 {
358 if(fstabf)
359 afclose(fstabf);
360 fstabf = NULL;
361 }
362
363 static generic_fsent_t _fsent;
364
365 int
get_fstab_nextentry(generic_fsent_t * fsent)366 get_fstab_nextentry(
367 generic_fsent_t *fsent)
368 {
369 struct statfs fsd;
370 char typebuf[FSTYPSZ];
371 static struct mnttab mnt;
372 char *dp, *ep;
373
374 if(!fread (&mnt, SIZEOF(mnt), 1, fstabf))
375 return 0;
376
377 fsent->fsname = mnt.mt_dev;
378 fsent->mntdir = mnt.mt_filsys;
379 fsent->fstype = "";
380
381 if (statfs (fsent->mntdir, &fsd, SIZEOF(fsd), 0) != -1
382 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) {
383 dp = typebuf;
384 ep = fsent->fstype = malloc(strlen(typebuf)+2);
385 while (*dp)
386 *ep++ = tolower(*dp++);
387 *ep=0;
388 }
389
390 if ( mnt.mt_ro_flg == MNT_READONLY ) {
391 fsent->mntopts = "ro";
392 } else {
393 fsent->mntopts = "rw";
394 }
395
396 fsent->freq = 0;
397 fsent->passno = 0;
398 return 1;
399 }
400
401 # else /* } { */
402
403 #define GETFSENT_TYPE "undefined"
404
405 # endif
406 # endif
407 # endif
408 #endif
409 #endif /* } */
410
411 /*
412 *=====================================================================
413 * Convert either a block or character device name to a character (raw)
414 * device name.
415 *
416 * static char *dev2rdev(const char *name);
417 *
418 * entry: name - device name to convert
419 * exit: matching character device name if found,
420 * otherwise returns the input
421 *
422 * The input must be an absolute path.
423 *
424 * The exit string area is always an alloc-d area that the caller is
425 * responsible for releasing.
426 *=====================================================================
427 */
428
429 static char *
dev2rdev(char * name)430 dev2rdev(
431 char * name)
432 {
433 char *fname = NULL;
434 struct stat st;
435 char *s;
436 int ch;
437
438 if(stat(name, &st) == 0 && !S_ISBLK(st.st_mode)) {
439 /*
440 * If the input is already a character device, just return it.
441 */
442 return stralloc(name);
443 }
444
445 s = name;
446 ch = *s++;
447
448 if(ch == '\0' || ch != '/') return stralloc(name);
449
450 ch = *s++; /* start after first '/' */
451 /*
452 * Break the input path at each '/' and create a new name with an
453 * 'r' before the right part. For instance:
454 *
455 * /dev/sd0a -> /dev/rsd0a
456 * /dev/dsk/c0t0d0s0 -> /dev/rdsk/c0t0d0s0 -> /dev/dsk/rc0t0d0s0
457 */
458 while(ch) {
459 if (ch == '/') {
460 s[-1] = '\0';
461 fname = newvstralloc(fname, name, "/r", s, NULL);
462 s[-1] = (char)ch;
463 if(stat(fname, &st) == 0 && S_ISCHR(st.st_mode)) return fname;
464 }
465 ch = *s++;
466 }
467 amfree(fname);
468 return stralloc(name); /* no match */
469 }
470
471 #ifndef IGNORE_FSTAB
472 static int samefile(struct stat[3], struct stat *);
473
474 static int
samefile(struct stat stats[3],struct stat * estat)475 samefile(
476 struct stat stats[3],
477 struct stat *estat)
478 {
479 int i;
480 for(i = 0; i < 3; ++i) {
481 if (stats[i].st_dev == estat->st_dev &&
482 stats[i].st_ino == estat->st_ino)
483 return 1;
484 }
485 return 0;
486 }
487 #endif /* !IGNORE_FSTAB */
488
489 int
search_fstab(char * name,generic_fsent_t * fsent,int check_dev)490 search_fstab(
491 char * name,
492 generic_fsent_t * fsent,
493 int check_dev)
494 {
495 #ifdef IGNORE_FSTAB
496 /* There is no real mount table so this will always fail and
497 * we are using GNU tar so we can just return here.
498 */
499 (void)name; /* Quiet unused parameter warning */
500 (void)fsent; /* Quiet unused parameter warning */
501 (void)check_dev; /* Quiet unused parameter warning */
502 return 0;
503 #else
504 struct stat stats[3];
505 char *fullname = NULL;
506 char *rdev = NULL;
507 int rc;
508
509 if (!name)
510 return 0;
511
512 memset(stats, 0, SIZEOF(stats));
513 stats[0].st_dev = stats[1].st_dev = stats[2].st_dev = (dev_t)-1;
514
515 if (stat(name, &stats[0]) == -1)
516 stats[0].st_dev = (dev_t)-1;
517 if (name[0] != '/') {
518 fullname = stralloc2(DEV_PREFIX, name);
519 if (stat(fullname, &stats[1]) == -1)
520 stats[1].st_dev = (dev_t)-1;
521 fullname = newstralloc2(fullname, RDEV_PREFIX, name);
522 if (stat(fullname, &stats[2]) == -1)
523 stats[2].st_dev = (dev_t)-1;
524 amfree(fullname);
525 }
526 else if (stat((rdev = dev2rdev(name)), &stats[1]) == -1)
527 stats[1].st_dev = (dev_t)-1;
528
529 amfree(rdev);
530
531 if (!open_fstab())
532 return 0;
533
534 rc = 0;
535 while(get_fstab_nextentry(fsent)) {
536 struct stat mntstat;
537 struct stat fsstat;
538 struct stat fsrstat;
539 int smnt = -1, sfs = -1, sfsr = -1;
540
541 amfree(rdev);
542
543 if(fsent->mntdir != NULL)
544 smnt = stat(fsent->mntdir, &mntstat);
545
546 if(fsent->fsname != NULL) {
547 sfs = stat(fsent->fsname, &fsstat);
548 sfsr = stat((rdev = dev2rdev(fsent->fsname)), &fsrstat);
549 if(check_dev == 1 && sfs == -1 && sfsr == -1)
550 continue;
551 }
552
553 if((fsent->mntdir != NULL &&
554 smnt != -1 &&
555 samefile(stats, &mntstat)) ||
556 (fsent->fsname != NULL &&
557 sfs != -1 &&
558 samefile(stats, &fsstat)) ||
559 (fsent->fsname != NULL &&
560 sfsr != -1 &&
561 samefile(stats, &fsrstat))) {
562 rc = 1;
563 break;
564 }
565 }
566 amfree(rdev);
567 close_fstab();
568 return rc;
569 #endif /* !IGNORE_FSTAB */
570 }
571
572 int
is_local_fstype(generic_fsent_t * fsent)573 is_local_fstype(
574 generic_fsent_t * fsent)
575 {
576 if(fsent->fstype == NULL) /* unknown, assume local */
577 return 1;
578
579 /* just eliminate fstypes known to be remote or unsavable */
580
581 return strcmp(fsent->fstype, "nfs") != 0 && /* NFS */
582 strcmp(fsent->fstype, "afs") != 0 && /* Andrew Filesystem */
583 strcmp(fsent->fstype, "swap") != 0 && /* Swap */
584 strcmp(fsent->fstype, "iso9660") != 0 && /* CDROM */
585 strcmp(fsent->fstype, "hs") != 0 && /* CDROM */
586 strcmp(fsent->fstype, "piofs") != 0; /* an AIX printer thing? */
587 }
588
589
590 char *
amname_to_devname(char * str)591 amname_to_devname(
592 char * str)
593 {
594 generic_fsent_t fsent;
595
596 if(search_fstab(str, &fsent, 1) && fsent.fsname != NULL)
597 str = fsent.fsname;
598 else if(search_fstab(str, &fsent, 0) && fsent.fsname != NULL)
599 str = fsent.fsname;
600
601 return dev2rdev(str);
602 }
603
604 char *
amname_to_dirname(char * str)605 amname_to_dirname(
606 char * str)
607 {
608 generic_fsent_t fsent;
609
610 if(search_fstab(str, &fsent, 1) && fsent.mntdir != NULL)
611 str = fsent.mntdir;
612 else if(search_fstab(str, &fsent, 0) && fsent.mntdir != NULL)
613 str = fsent.mntdir;
614
615 return stralloc(str);
616 }
617
amname_to_fstype(char * str)618 char *amname_to_fstype(
619 char * str)
620 {
621 generic_fsent_t fsent;
622
623 if (!search_fstab(str, &fsent, 1) && !search_fstab(str, &fsent, 0))
624 return stralloc("");
625
626 return stralloc(fsent.fstype);
627 }
628
629 #ifdef TEST
630
631 void print_entry(generic_fsent_t *fsent);
632
633 void
print_entry(generic_fsent_t * fsent)634 print_entry(
635 generic_fsent_t * fsent)
636 {
637 #define nchk(s) ((s)? (s) : "<NULL>")
638 g_printf("%-20.20s %-14.14s %-7.7s %4d %5d %s\n",
639 nchk(fsent->fsname), nchk(fsent->mntdir), nchk(fsent->fstype),
640 fsent->freq, fsent->passno, nchk(fsent->mntopts));
641 }
642
643 int
main(int argc,char ** argv)644 main(
645 int argc,
646 char ** argv)
647 {
648 generic_fsent_t fsent;
649 char *s;
650 char *name = NULL;
651
652 /*
653 * Configure program for internationalization:
654 * 1) Only set the message locale for now.
655 * 2) Set textdomain for all amanda related programs to "amanda"
656 * We don't want to be forced to support dozens of message catalogs.
657 */
658 setlocale(LC_MESSAGES, "C");
659 textdomain("amanda");
660
661 safe_fd(-1, 0);
662
663 set_pname("getfsent");
664
665 dbopen(NULL);
666
667 /* Don't die when child closes pipe */
668 signal(SIGPIPE, SIG_IGN);
669
670 if(!open_fstab()) {
671 g_fprintf(stderr, _("getfsent_test: could not open fstab\n"));
672 return 1;
673 }
674
675 g_printf("getfsent (%s)\n",GETFSENT_TYPE);
676 g_printf("l/r fsname mntdir fstype freq pass# mntopts\n");
677 while(get_fstab_nextentry(&fsent)) {
678 g_printf("%c ",is_local_fstype(&fsent)? 'l' : 'r');
679 print_entry(&fsent);
680 }
681 g_printf("--------\n");
682
683 close_fstab();
684
685 name = newstralloc(name, "/usr");
686 if(search_fstab(name, &fsent, 1) || search_fstab(name, &fsent, 0)) {
687 g_printf(_("Found %s mount for %s:\n"),
688 is_local_fstype(&fsent)? _("local") : _("remote"), name);
689 print_entry(&fsent);
690 }
691 else
692 g_printf(_("Mount for %s not found\n"), name);
693
694 name = newstralloc(name, "/");
695 if(search_fstab(name, &fsent, 1) || search_fstab(name, &fsent, 0)) {
696 g_printf(_("Found %s mount for %s:\n"),
697 is_local_fstype(&fsent)? _("local") : _("remote"), name);
698 print_entry(&fsent);
699 }
700 else
701 g_printf(_("Mount for %s not found\n"), name);
702
703 name = newstralloc(name, "/");
704 s = amname_to_fstype(name);
705 g_printf(_("fstype of `%s': %s\n"), name, s);
706 amfree(s);
707 name = newstralloc(name, "/dev/root");
708 s = amname_to_fstype(name);
709 g_printf(_("fstype of `%s': %s\n"), name, s);
710 amfree(s);
711 name = newstralloc(name, "/usr");
712 s = amname_to_fstype(name);
713 g_printf(_("fstype of `%s': %s\n"), name, s);
714 amfree(s);
715 name = newstralloc(name, "c0t3d0s0");
716 s = amname_to_fstype(name);
717 g_printf(_("fstype of `%s': %s\n"), name, s);
718 amfree(s);
719
720 name = newstralloc(name, "/tmp/foo");
721 s = amname_to_devname(name);
722 g_printf(_("device of `%s': %s\n"), name, s);
723 amfree(s);
724 s = amname_to_dirname(name);
725 g_printf(_("dirname of `%s': %s\n"), name, s);
726 amfree(s);
727 s = amname_to_fstype(name);
728 g_printf(_("fstype of `%s': %s\n"), name, s);
729 amfree(s);
730
731 name = newstralloc(name, "./foo");
732 s = amname_to_devname(name);
733 g_printf(_("device of `%s': %s\n"), name, s);
734 amfree(s);
735 s = amname_to_dirname(name);
736 g_printf(_("dirname of `%s': %s\n"), name, s);
737 amfree(s);
738 s = amname_to_fstype(name);
739 g_printf(_("fstype of `%s': %s\n"), name, s);
740 amfree(s);
741
742 while (--argc > 0) {
743 name = newstralloc(name, *++argv);
744 s = amname_to_devname(name);
745 g_printf(_("device of `%s': %s\n"), name, s);
746 amfree(s);
747 s = amname_to_dirname(name);
748 g_printf(_("dirname of `%s': %s\n"), name, s);
749 amfree(s);
750 s = amname_to_fstype(name);
751 g_printf(_("fstype of `%s': %s\n"), name, s);
752 amfree(s);
753 }
754
755 amfree(name);
756
757 dbclose();
758 return 0;
759 }
760
761 #endif
762