⛏️ index : haiku.git

/*
 * Copyright 2002-2009, Haiku Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Jonas Sundstrom, jonas.sundstrom@kirilla.com
 *		Stephan Aßmus <superstippi@gmx.de>
 */

#include <fs_info.h>

#include <stdio.h>
#include <string.h>

#include <DiskDevice.h>
#include <DiskDeviceRoster.h>
#include <Volume.h>


static void
usage()
{
	fprintf(stderr, 
		"Usage: isvolume {-OPTION} [volumename]\n"
		"   Where OPTION is one of:\n"
		"      -readonly         - volume is read-only\n"
		"      -readonly-partion - partition for the volume is read-only\n"
		"      -query            - volume supports queries\n"
		"      -attribute        - volume supports attributes\n"
		"      -mime             - volume supports MIME information\n"
		"      -shared           - volume is shared\n"
		"      -persistent       - volume is backed on permanent storage\n"
		"      -removable        - volume is on removable media\n"
		"   If the option is true for the named volume, 'yes' is printed\n"
		"   and if the option is false, 'no' is printed. Multiple options\n"
		"   can be specified in which case all of them must be true.\n\n"
		"   If no volume is specified, the volume of the current directory is "
		"assumed.\n");
}


int
main(int argc, char** argv)
{
	dev_t volumeDevice = dev_for_path(".");
	uint32 isVolumeFlags = 0;
	fs_info volumeInfo;
	bool doPartitionReadOnlyCheck = false;

	for (int i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "--help")) {
			usage();
			return 0;
		}
	
		if (argv[i][0] == '-') {
			if (strcmp(argv[i], "-readonly") == 0)
				isVolumeFlags |= B_FS_IS_READONLY;
			else if (strcmp(argv[i], "-query") == 0)
				isVolumeFlags |= B_FS_HAS_QUERY;
			else if (strcmp(argv[i], "-attribute") == 0)
				isVolumeFlags |= B_FS_HAS_ATTR;
			else if (strcmp(argv[i], "-mime") == 0)
				isVolumeFlags |= B_FS_HAS_MIME;
			else if (strcmp(argv[i], "-shared") == 0)
				isVolumeFlags |= B_FS_IS_SHARED;
			else if (strcmp(argv[i], "-persistent") == 0)
				isVolumeFlags |= B_FS_IS_PERSISTENT;
			else if (strcmp(argv[i], "-removable") == 0)
				isVolumeFlags |= B_FS_IS_REMOVABLE;
			else if (strcmp(argv[i], "-readonly-partion"))
				doPartitionReadOnlyCheck = true;
			else {	
				fprintf(stderr,
					"%s: option %s is not understood (use --help for help)\n",
					argv[0], argv[i]);
				return 1;
			}
		} else {
			volumeDevice = dev_for_path(argv[i]);

			if (volumeDevice < 0) {
				fprintf(stderr, "%s: can't get information about volume: %s\n",
					argv[0], argv[i]);
				return 1;
			}
		}
	}

	if (doPartitionReadOnlyCheck) {
		// This requires an extra code-path, because volumes may now appear
		// writable, but only because of the "write" file-system overlay.
		BVolume volume(volumeDevice);
		status_t ret = volume.InitCheck();
		if (ret != B_OK) {
			fprintf(stderr, "%s: failed to get BVolume for device %" B_PRIdDEV
				": %s\n", argv[0], volumeDevice, strerror(ret));
			return 1;
		}

		BDiskDeviceRoster roster;
		BDiskDevice diskDevice;
		BPartition* partition;
		ret = roster.FindPartitionByVolume(volume, &diskDevice, &partition);
		if (ret != B_OK) {
			fprintf(stderr, "%s: failed to get partition for device %" B_PRIdDEV
				": %s\n", argv[0], volumeDevice, strerror(ret));
			return 1;
		}
		// check this option directly and not via fs_stat_dev()
		if (partition->IsReadOnly()) {
			printf("yes\n");
			return 0;
		}
	}

	if (fs_stat_dev(volumeDevice, &volumeInfo) == B_OK) {
		if (volumeInfo.flags & isVolumeFlags)
			printf("yes\n");
		else
			printf("no\n");

		return 0;
	} else {
		fprintf(stderr, "%s: can't get information about dev_t: %" B_PRIdDEV
			"\n", argv[0], volumeDevice);
		return 1;
	}
}