haiku/src/bin/settype.cpp
Ingo Weinhold 338b8dc301 Merged changes from branch build_system_redesign at revision 14573.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14574 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-10-29 16:27:43 +00:00

242 lines
5.1 KiB
C++

/*
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <AppFileInfo.h>
#include <Mime.h>
static const char *kCommandName = "settype";
static int kArgc;
static const char *const *kArgv;
// usage
const char *kUsage =
"Usage: %s <options> <file> ...\n"
"\n"
"Sets the MIME type, signature, and/or preferred application of one or more\n"
"files.\n"
"\n"
"Options:\n"
" -h, --help\n"
" - Print this help text and exit.\n"
" -preferredAppSig <signature>\n"
" - Set the preferred application of the given files to\n"
" <signature>.\n"
" -s <signature>\n"
" - Set the application signature of the given files to\n"
" <signature>.\n"
" -t <type>\n"
" - Set the MIME type of the given files to <type>.\n"
;
// print_usage
static void
print_usage(bool error)
{
// get command name
const char *commandName = NULL;
if (kArgc > 0) {
if (const char *lastSlash = strchr(kArgv[0], '/'))
commandName = lastSlash + 1;
else
commandName = kArgv[0];
}
if (!commandName || strlen(commandName) == 0)
commandName = kCommandName;
// print usage
fprintf((error ? stderr : stdout), kUsage, commandName, commandName,
commandName);
}
// print_usage_and_exit
static void
print_usage_and_exit(bool error)
{
print_usage(error);
exit(error ? 1 : 0);
}
// next_arg
static const char *
next_arg(int &argi, bool optional = false)
{
if (argi >= kArgc) {
if (!optional)
print_usage_and_exit(true);
return NULL;
}
return kArgv[argi++];
}
// check_mime_type
static void
check_mime_type(const char *type)
{
// check type
if (type) {
if (!BMimeType::IsValid(type)) {
fprintf(stderr, "\"%s\" is no valid MIME type.\n", type);
exit(1);
}
}
}
// main
int
main(int argc, const char *const *argv)
{
kArgc = argc;
kArgv = argv;
// parameters
const char **files = new const char*[argc];
int fileCount = 0;
const char *type = NULL;
const char *signature = NULL;
const char *preferredApp = NULL;
// parse the arguments
for (int argi = 1; argi < argc; ) {
const char *arg = argv[argi++];
if (arg[0] == '-') {
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
print_usage_and_exit(false);
} else if (strcmp(arg, "-preferredAppSig") == 0) {
preferredApp = next_arg(argi);
} else if (strcmp(arg, "-s") == 0) {
signature = next_arg(argi);
} else if (strcmp(arg, "-t") == 0) {
type = next_arg(argi);
} else {
fprintf(stderr, "Error: Invalid option: \"%s\"\n", arg);
print_usage_and_exit(true);
}
} else {
// file
files[fileCount++] = arg;
}
}
// check parameters
if (!preferredApp && !signature && !type) {
fprintf(stderr, "Error: At least one option of \"-preferredAppSig\", "
"\"-s\", and \"-t\" must be given.\n");
print_usage_and_exit(true);
}
if (fileCount == 0) {
fprintf(stderr, "Error: No file specified.\n");
print_usage_and_exit(true);
}
// check for valid MIME types
check_mime_type(preferredApp);
check_mime_type(type);
check_mime_type(signature);
// iterate through the files
for (int i = 0; i < fileCount; i++) {
const char *fileName = files[i];
// check, whether the file exists
BEntry entry;
status_t error = entry.SetTo(fileName, false);
if (error != B_OK) {
fprintf(stderr, "Error: Can't access file \"%s\": %s\n",
fileName, strerror(error));
exit(1);
}
if (!entry.Exists()) {
fprintf(stderr, "Error: \"%s\": No such file or directory.\n",
fileName);
exit(1);
}
// ... and has the right type
if (signature && !entry.IsFile()) {
fprintf(stderr, "Error: \"%s\" is not a file. Signatures can only "
"be set for executable files.\n", fileName);
exit(1);
}
// open the file
BFile file;
BNode _node;
BNode &node = (signature ? file : _node);
error = (signature ? file.SetTo(fileName, B_READ_WRITE)
: node.SetTo(fileName));
if (error != B_OK) {
fprintf(stderr, "Error: Failed to open file \"%s\": %s\n",
fileName, strerror(error));
exit(1);
}
// prepare an node/app info object
BAppFileInfo appInfo;
BNodeInfo _nodeInfo;
BNodeInfo &nodeInfo = (signature ? appInfo : _nodeInfo);
error = (signature ? appInfo.SetTo(&file) : nodeInfo.SetTo(&node));
if (error != B_OK) {
fprintf(stderr, "Error: Failed to open file \"%s\": %s\n",
fileName, strerror(error));
exit(1);
}
// set preferred app
if (preferredApp) {
error = nodeInfo.SetPreferredApp(preferredApp);
if (error != B_OK) {
fprintf(stderr, "Error: Failed to set the preferred "
"application of file \"%s\": %s\n", fileName,
strerror(error));
exit(1);
}
}
// set type
if (type) {
error = nodeInfo.SetType(type);
if (error != B_OK) {
fprintf(stderr, "Error: Failed to set the MIME type of file "
"\"%s\": %s\n", fileName, strerror(error));
exit(1);
}
}
// set signature
if (signature) {
error = appInfo.SetSignature(signature);
if (error != B_OK) {
fprintf(stderr, "Error: Failed to set the signature of file "
"\"%s\": %s\n", fileName, strerror(error));
exit(1);
}
}
}
return 0;
}