⛏️ index : haiku.git

/*
 * Copyright 2002-2007, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Ryan Fleet
 *		Vasilis Kaoutsis
 */


#include <Application.h>
#include <AppFileInfo.h>

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


void
usage()
{
	printf("usage: version [OPTION] FILENAME [FILENAME2, ...]\n"
		"Returns the version of a file.\n\n"
		"        -h, --help              this usage message\n"
		"        -l, --long              print long version information of FILENAME\n"
		"        -n, --numerical         print in numerical mode\n"
		"                                (Major miDdle miNor Variety Internal)\n"
		"        -s, --system            print system version instead of app version\n"
		"        --version               print version information for this command\n");
}


status_t
get_version(const char *filename, version_kind kind, bool longFlag, bool numericalFlag)
{
	BFile file(filename, O_RDONLY);
	if (file.InitCheck() != B_OK) {
		printf("Couldn't get file info!\n");
		return B_FILE_ERROR;
	}

	BAppFileInfo info(&file);
	if (info.InitCheck() != B_OK) {
		printf("Couldn't get file info!\n");
		return B_FILE_ERROR;
	}

	version_info version;
	if (info.GetVersionInfo(&version, kind) != B_OK) {
		printf("Version unknown!\n");
		return B_ERROR;
	}

	if (longFlag) {
		printf("%s\n", version.long_info);
		return B_OK;
	}

	if (numericalFlag) {
		printf("%lu ", version.major);
		printf("%lu ", version.middle);
		printf("%lu ", version.minor);

		switch (version.variety) {
			case B_DEVELOPMENT_VERSION:
				printf("d ");
				break;

			case B_ALPHA_VERSION:
				printf("a ");
				break;

			case B_BETA_VERSION:
				printf("b ");
				break;

			case B_GAMMA_VERSION:
				printf("g ");
				break;

			case B_GOLDEN_MASTER_VERSION:
				printf("gm ");
				break;

			case B_FINAL_VERSION:
				printf("f ");
				break;	
		}

		printf("%lu\n", version.internal);
		return B_OK;
	}

	printf("%s\n", version.short_info);
	return B_OK;
}


/*!
	determines whether  \a string1 contains at least one or more of the characters
	of \a string2 but none of which \a string2 doesn't contain. 

	examples:
	true == ("hel" == "help"); true == ("help" == "help"); true == ("h" == "help");
	false == ("held" == "help"); false == ("helped" == "help"); 
*/
bool
str_less_equal(const char *str1, const char *str2)
{
	char *ptr1 = const_cast<char*>(str1);
	char *ptr2 = const_cast<char*>(str2);

	while (*ptr1 != '\0') {	
		if (*ptr1 != *ptr2)
			return false;
		++ptr1;
		++ptr2;
	}
	return true;
}


int
main(int argc, char *argv[])
{
	BApplication app("application/x.vnd.Haiku-version");
	version_kind kind = B_APP_VERSION_KIND;
	bool longFlag = false;
	bool numericalFlag = false;
	int i;

	if (argc < 2) {
		usage();
		return 0;
	}
	
	for (i = 1; i < argc; ++i) {
		if (argv[i][0] == '-') {
			char *ptr = argv[i];
			++ptr;

			if (*ptr == '-') {
				bool lessEqual = false;
				++ptr;

				if (*ptr == 'h') {
					lessEqual = str_less_equal(ptr, "help");
					if (lessEqual) {
						usage();
						return 0;
					}
				} else if (*ptr == 'l') {
					lessEqual = str_less_equal(ptr, "long");
					if (lessEqual)
						longFlag = true;
				} else if (*ptr == 'n') {
					lessEqual = str_less_equal(ptr, "numerical");
					if (lessEqual)
						numericalFlag = true;
				} else if (*ptr == 's') {
					lessEqual = str_less_equal(ptr, "system");
					if (lessEqual)
						kind = B_SYSTEM_VERSION_KIND;
				} else if (*ptr == 'v') {
					lessEqual = str_less_equal(ptr, "version");
					if (lessEqual) {
						get_version(argv[0], B_APP_VERSION_KIND, false, false);
						return 0;
					}
				}

				if (!lessEqual)
					printf("%s unrecognized option `%s'\n", argv[0], argv[i]);
			} else {
				while (*ptr != '\0') {
					if (*ptr == 'h') {
						usage();
						return 0;
					} else if (*ptr == 's')
						kind = B_SYSTEM_VERSION_KIND;
					else if (*ptr == 'l')
						longFlag = true;
					else if (*ptr == 'n')
						numericalFlag = true;
					else {
						printf("%s: invalid option -- %c\n", argv[0], *ptr);
						return 1;
					}

					if (argc < 3) {
						printf("%s: missing FILENAME(S) \n", argv[0]);
						return 1;
					}

					++ptr;
				}
			}
		}
	}

	for (i = 1; i < argc; ++i) {
		if (argv[i][0] != '-'
			&& get_version(argv[i], kind, longFlag, numericalFlag) != B_OK)
			return 1;
	}

	return 0;
}