Ejemplo n.º 1
0
int main(int argc, char **argv)
{
	g_BufferedMemorySize = 100;

	string compressorName;
	string commandLineOptions;

	std::vector<string> fuseOptions;
	fuseOptions.push_back(argv[0]);

	po::options_description desc("Usage: " PACKAGE "_offline [options] path\n"
	                                "\nPath may be directory or file.\n"
	                                "\nNo options mean decompression mode.\n\n"
	                                "Allowed options");
	desc.add_options()
		("options,o", po::value<string>(&commandLineOptions),
				"fc_c:arg  - compression method (lzo/bzip2/zlib/lzma)\n"
				"            (default: gz)\n"
				"fc_b:arg  - size of blocks in kilobytes\n"
				"            (default: 100)\n"
				"fc_d      - run in debug mode\n"
				"fc_ma:arg - files with passed mime types to be\n"
				"            always not compressed\n"
				"fc_mr:arg - files with passed mime types to be\n"
				"            always compressed\n"
				"\nOther options are passed directly to fuse library. See fuse documentation for full list of supported options.\n")
		("dir_lower", po::value<string>(&g_dirLower), "path")
		("help,h", "print this help")
		("version,v", "print version")
		("quiet,q", "quiet mode")
	;

	po::positional_options_description pdesc;
	pdesc.add("dir_lower", 1);

	po::variables_map vm;
	try {
		po::store(po::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vm);
	} catch (...) {
		print_help(desc);
		exit(EXIT_FAILURE);
	}
	po::notify(vm);

	if (vm.count("help"))
	{
		print_help(desc);
		exit(EXIT_SUCCESS);
	}
	if (vm.count("version"))
	{
		print_license();
		exit(EXIT_SUCCESS);
	}
	if (vm.count("quiet"))
	{
		g_QuietMode = true;
	}

	g_RLog = new rlog::RLog("FuseCompress_offline", g_QuietMode ? LOG_NOTICE : LOG_INFO, true);

	if (vm.count("options"))
	{
		typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
		boost::char_separator<char> sep(",");
		tokenizer tokens(commandLineOptions, sep);

		for (tokenizer::iterator tok_it = tokens.begin(); tok_it != tokens.end(); ++tok_it)
		{
			if ((*tok_it).find_first_of("fc_", 0, 3) == 0)
			{
				typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
				boost::char_separator<char> sep(":");
				tokenizer tokens(*tok_it, sep);

				tokenizer::iterator key = tokens.begin();
				tokenizer::iterator value = key; ++value;

				if (*key == "fc_c")
				{
					if (value == tokens.end())
					{
						rError("Compression type not set!");
						exit(EXIT_FAILURE);
					}
					compressorName = *value;
				}
				if (*key == "fc_b")
				{
					if (value == tokens.end())
					{
						rError("Block size not set!");
						exit(EXIT_FAILURE);
					}
					g_BufferedMemorySize = boost::lexical_cast<unsigned int>(*value);
				}
				if (*key == "fc_d")
				{
					g_DebugMode = true;
					g_RLog->setLevel(LOG_DEBUG);
				}
				if (*key == "fc_ma")
				{
					if (value == tokens.end())
					{
						rError("Mime type(s) not set!");
						exit(EXIT_FAILURE);
					}
					g_CompressedMagic.Add(*value);
				}
				if (*key == "fc_mr")
				{
					if (value == tokens.end())
					{
						rError("Mime type(s) not set!");
						exit(EXIT_FAILURE);
					}
					g_CompressedMagic.Remove(*value);
				}
			}
			else
			{
				fuseOptions.push_back("-o");
				fuseOptions.push_back(*tok_it);
			}
		}
	}
	if (!vm.count("dir_lower"))
	{
		print_help(desc);
		exit(EXIT_FAILURE);
	}

	g_BufferedMemorySize *= 1024;

	if (compressorName != "")
	{
		g_RawOutput = false;

		if (g_CompressionType.parseType(compressorName) == false)
		{
			rError("Compressor %s not found!", compressorName.c_str());
			exit(EXIT_FAILURE);
		}
	}

	fs::path pathLower(g_dirLower
#if BOOST_VERSION <= 104600
            , fs::native
#endif
            );

	if (!pathLower.is_complete())
	{
		char cwd[PATH_MAX];

		// Transform relative path to absolute path.

		if (getcwd(cwd, sizeof(cwd)) == NULL)
		{
			rError("Cannot determine current working directory!");
			exit(EXIT_FAILURE);
		}

        pathLower = fs::path(cwd
#if BOOST_VERSION <= 104600
                , fs::native
#endif
                ) / pathLower;
	}

	// Set signal handler to catch SIGINT (CTRL+C).

	struct sigaction setup_kill;
	memset(&setup_kill, 0, sizeof(setup_kill));
	setup_kill.sa_handler = catch_kill;
	sigaction(SIGINT, &setup_kill, NULL);

	// Iterate over directory structure and execute compress
	// for every files there.

	if (nftw(const_cast<char *>(pathLower.string().c_str()), compress, 100, FTW_PHYS | FTW_CHDIR))
		exit(EXIT_FAILURE);

	exit(EXIT_SUCCESS);
}
Ejemplo n.º 2
0
int main(int argc, char **argv)
{
	g_BufferedMemorySize = 100;
	g_DebugMode = false;

	string compressorName;
	string commandLineOptions;

	vector<string> fuseOptions;
	fuseOptions.push_back(argv[0]);

	po::options_description desc("Usage: " PACKAGE " [options] dir_lower dir_mount\n" "\nAllowed options");
	desc.add_options()
		("options,o", po::value<string>(&commandLineOptions),
				"fc_c:arg          - compression method\n"
				"                    (lzo/bzip2/zlib/lzma)\n"
				"                    (default: zlib)\n"
				"fc_b:arg          - size of blocks in kilobytes\n"
				"                    (default: 100)\n"
				"fc_d              - run in debug mode\n"
				"fc_ma:\"arg1;arg2\" - files with passed mime types to be\n"
				"                    always not compressed\n"
				"fc_mr:\"arg1;arg2\" - files with passed mime types to be\n"
				"                    always compressed\n"
				"\nOther options are passed directly to fuse library. See fuse documentation for full list of supported options.\n")
		("dir_lower", po::value<string>(&g_dirLower), "storage directory")
		("dir_mount", po::value<string>(&g_dirMount), "mount point")
		("help,h", "print this help")
		("version,v", "print version")
	;

	po::positional_options_description pdesc;
	pdesc.add("dir_lower", 1);
	pdesc.add("dir_mount", 1);

	po::variables_map vm;
	try {
		po::store(po::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vm);
	} catch (...) {
		print_help(desc);
		exit(EXIT_FAILURE);
	}
	po::notify(vm);

	if (vm.count("help"))
	{
		print_help(desc);
		exit(EXIT_SUCCESS);
	}
	if (vm.count("version"))
	{
		print_license();
		exit(EXIT_SUCCESS);
	}
	if (vm.count("options"))
	{
		typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
		boost::char_separator<char> sep(",");
		tokenizer tokens(commandLineOptions, sep);

		for (tokenizer::iterator tok_it = tokens.begin(); tok_it != tokens.end(); ++tok_it)
		{
			if ((*tok_it).find_first_of("fc_", 0, 3) == 0)
			{
				typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
				boost::char_separator<char> sep(":");
				tokenizer tokens(*tok_it, sep);

				tokenizer::iterator key = tokens.begin();
				tokenizer::iterator value = key; ++value;

				if (*key == "fc_c")
				{
					if (value == tokens.end())
					{
						std::cerr << "Compression type not set!" << std::endl;
						exit(EXIT_FAILURE);
					}
					compressorName = *value;
				}
				if (*key == "fc_b")
				{
					if (value == tokens.end())
					{
						std::cerr << "Block size not set!" << std::endl;
						exit(EXIT_FAILURE);
					}
					g_BufferedMemorySize = boost::lexical_cast<unsigned int>(*value);
				}
				if (*key == "fc_d")
				{
					fuseOptions.push_back("-f");
					g_DebugMode = true;
				}
				if (*key == "fc_ma")
				{
					if (value == tokens.end())
					{
						std::cerr << "Mime type(s) not set!" << std::endl;
						exit(EXIT_FAILURE);
					}
					g_CompressedMagic.Add(*value);
				}
				if (*key == "fc_mr")
				{
					if (value == tokens.end())
					{
						std::cerr << "Mime type(s) not set!" << std::endl;
						exit(EXIT_FAILURE);
					}
					g_CompressedMagic.Remove(*value);
				}
			}
			else
			{
				fuseOptions.push_back("-o");
				fuseOptions.push_back(*tok_it);
			}
		}
	}
	if (vm.count("dir_lower"))
	{
		g_dirLower = vm["dir_lower"].as<string>();
	}
	else
	{
		print_help(desc);
		exit(EXIT_FAILURE);
	}
	if (vm.count("dir_mount"))
	{
		g_dirMount = vm["dir_mount"].as<string>();
	}
	else
	{
		print_help(desc);
		exit(EXIT_FAILURE);
	}

	g_BufferedMemorySize *= 1024;
	
	// Set up default options for fuse.
	// 
	fuseOptions.push_back("-o");
	fuseOptions.push_back("default_permissions,use_ino,kernel_cache");
	fuseOptions.push_back(g_dirMount);

	// Set default transformation as user wanted.
	// 
	if ((compressorName != "") &&
	    (g_CompressionType.parseType(compressorName) == false))
	{
		cerr << "Compressor " << compressorName << " not found!" << endl;
		exit(EXIT_FAILURE);
	}
	
	DIR *dir;
	if ((dir = opendir(g_dirLower.c_str())) == NULL)
	{
		int errns = errno;

		cerr << "Failed to open storage directory "
		     << "'" << g_dirLower << "': " << strerror(errns) << endl;
		exit(EXIT_FAILURE);
	}

	vector<const char *> fuse_c_str;
	for (unsigned int i = 0; i < fuseOptions.size(); ++i)
	{
		fuse_c_str.push_back((fuseOptions[i].c_str()));
	}

	init_log();
	FuseCompress fusecompress;

	umask(0);
	return fusecompress.Run(dir, fuse_c_str.size(), &fuse_c_str[0]);
}
Ejemplo n.º 3
0
ssize_t Compress::write(const char *buf, size_t size, off_t offset)
{
	// Spurious call to write when file has not been opened
	// happened during testing...

	if (m_fd == -1)
	{
		rWarning("Compress::write Spurios call detected!");

		errno = -EBADF;
		return -1;
	}
	assert (m_fd != -1);

	rDebug("Compress::write size: 0x%lx, offset: 0x%lx",
	       (long int) size, (long int) offset);

	// We have an oppourtunity to decide whether we really
	// want to compress the file. We use file magic library
	// to detect mime type of the file to decide the compress
	// strategy.
 
	if ((m_IsCompressed == true) &&
	    (offset == 0) &&
	    (m_RawFileSize == FileHeader::MaxSize) &&
	    (g_CompressedMagic.isNativelyCompressed(buf, size)))
	{
		m_IsCompressed = false;
	}

	if (m_IsCompressed == false)
	{
		return pwrite(m_fd, buf, size, offset);
	}
	else
	{
		// If we write data containing only zeros to the end of the file,
		// we can just increase size of the file. No need to really
		// compress and write buffer of zeros...

		if ((m_fh.size == offset) && FileUtils::isZeroOnly(buf, size))
		{
			assert(size > 0);
			m_fh.size = offset + size;
		}
		else
		{
			off_t rawFileSize = writeCompressed(m_lm, offset, m_RawFileSize, buf, size, m_fd, m_RawFileSize);
			if (rawFileSize == -1)
				return -1;
			m_RawFileSize = rawFileSize;

			assert(size > 0);
			m_fh.size = max(m_fh.size, (off_t) (offset + size));

			// Defragment the file only if raw file size if bigger than 4096 bytes
			// and raw file size is about 20% bigger than it would be uncompressed.

			if (m_RawFileSize > 4096 && m_RawFileSize > m_fh.size + ((m_fh.size * 2) / 10))
			{
				DefragmentFast();
			}
		}

		return size;
	}
}