1/*
2 * Copyright 2002-2009, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Jonas Sundstrom, jonas.sundstrom@kirilla.com
7 *		Stephan Aßmus <superstippi@gmx.de>
8 */
9
10#include <fs_info.h>
11
12#include <stdio.h>
13#include <string.h>
14
15#include <DiskDevice.h>
16#include <DiskDeviceRoster.h>
17#include <Volume.h>
18
19
20static void
21usage()
22{
23	fprintf(stderr,
24		"Usage: isvolume {-OPTION} [volumename]\n"
25		"   Where OPTION is one of:\n"
26		"      -readonly         - volume is read-only\n"
27		"      -readonly-partion - partition for the volume is read-only\n"
28		"      -query            - volume supports queries\n"
29		"      -attribute        - volume supports attributes\n"
30		"      -mime             - volume supports MIME information\n"
31		"      -shared           - volume is shared\n"
32		"      -persistent       - volume is backed on permanent storage\n"
33		"      -removable        - volume is on removable media\n"
34		"   If the option is true for the named volume, 'yes' is printed\n"
35		"   and if the option is false, 'no' is printed. Multiple options\n"
36		"   can be specified in which case all of them must be true.\n\n"
37		"   If no volume is specified, the volume of the current directory is "
38		"assumed.\n");
39}
40
41
42int
43main(int argc, char** argv)
44{
45	dev_t volumeDevice = dev_for_path(".");
46	uint32 isVolumeFlags = 0;
47	fs_info volumeInfo;
48	bool doPartitionReadOnlyCheck = false;
49
50	for (int i = 1; i < argc; i++) {
51		if (!strcmp(argv[i], "--help")) {
52			usage();
53			return 0;
54		}
55
56		if (argv[i][0] == '-') {
57			if (strcmp(argv[i], "-readonly") == 0)
58				isVolumeFlags |= B_FS_IS_READONLY;
59			else if (strcmp(argv[i], "-query") == 0)
60				isVolumeFlags |= B_FS_HAS_QUERY;
61			else if (strcmp(argv[i], "-attribute") == 0)
62				isVolumeFlags |= B_FS_HAS_ATTR;
63			else if (strcmp(argv[i], "-mime") == 0)
64				isVolumeFlags |= B_FS_HAS_MIME;
65			else if (strcmp(argv[i], "-shared") == 0)
66				isVolumeFlags |= B_FS_IS_SHARED;
67			else if (strcmp(argv[i], "-persistent") == 0)
68				isVolumeFlags |= B_FS_IS_PERSISTENT;
69			else if (strcmp(argv[i], "-removable") == 0)
70				isVolumeFlags |= B_FS_IS_REMOVABLE;
71			else if (strcmp(argv[i], "-readonly-partion"))
72				doPartitionReadOnlyCheck = true;
73			else {
74				fprintf(stderr,
75					"%s: option %s is not understood (use --help for help)\n",
76					argv[0], argv[i]);
77				return 1;
78			}
79		} else {
80			volumeDevice = dev_for_path(argv[i]);
81
82			if (volumeDevice < 0) {
83				fprintf(stderr, "%s: can't get information about volume: %s\n",
84					argv[0], argv[i]);
85				return 1;
86			}
87		}
88	}
89
90	if (doPartitionReadOnlyCheck) {
91		// This requires an extra code-path, because volumes may now appear
92		// writable, but only because of the "write" file-system overlay.
93		BVolume volume(volumeDevice);
94		status_t ret = volume.InitCheck();
95		if (ret != B_OK) {
96			fprintf(stderr, "%s: failed to get BVolume for device %" B_PRIdDEV
97				": %s\n", argv[0], volumeDevice, strerror(ret));
98			return 1;
99		}
100
101		BDiskDeviceRoster roster;
102		BDiskDevice diskDevice;
103		BPartition* partition;
104		ret = roster.FindPartitionByVolume(volume, &diskDevice, &partition);
105		if (ret != B_OK) {
106			fprintf(stderr, "%s: failed to get partition for device %" B_PRIdDEV
107				": %s\n", argv[0], volumeDevice, strerror(ret));
108			return 1;
109		}
110		// check this option directly and not via fs_stat_dev()
111		if (partition->IsReadOnly()) {
112			printf("yes\n");
113			return 0;
114		}
115	}
116
117	if (fs_stat_dev(volumeDevice, &volumeInfo) == B_OK) {
118		if (volumeInfo.flags & isVolumeFlags)
119			printf("yes\n");
120		else
121			printf("no\n");
122
123		return 0;
124	} else {
125		fprintf(stderr, "%s: can't get information about dev_t: %" B_PRIdDEV
126			"\n", argv[0], volumeDevice);
127		return 1;
128	}
129}
130