⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basepkg.cc

📁 About: Paco (pacKAGE oRGANIZER) is a simple, yet powerful tool to aid package management when insta
💻 CC
字号:
//=======================================================================// BasePkg.cc//-----------------------------------------------------------------------// This file is part of the package paco// Copyright (C) 2004-2007 David Rosal <david.3r@gmail.com>// For more information visit http://paco.sourceforge.net//=======================================================================#include "config.h"#include "paco.h"#include "File.h"#include "BaseConfig.h"#include "BasePkg.h"#include <cstring>#include <fstream>#include <algorithm>#include <cctype>// For *BSD statfs()#if HAVE_SYS_PARAM_H#	include <sys/param.h>#endif#if HAVE_SYS_MOUNT_H#	include <sys/mount.h>#endif#if (HAVE_SYS_STATVFS_H && HAVE_STATVFS)#	define STATFS statvfs#	include <sys/statvfs.h>#elif HAVE_STATFS#	define STATFS statfs#	if HAVE_SYS_VFS_H#		include <sys/vfs.h>#	elif HAVE_SYS_STATFS#		include <sys/statfs.h>#	endif#elif STATFS#	undef STATFS#endifusing std::string;using namespace Paco;BasePkg::BasePkg(string const& __name):	mName(__name),	mLog(BaseConfig::logdir() + "/" + mName),	mDate(0),	mSizeInst(0),	mSizeMiss(0),	mFilesInst(0),	mFilesMiss(0),	mSortType(NO_SORT),	mSortReverse(false),	mConfOpts(){	if (mName.empty() || ispunct(mName.at(0)))		throw ConstructorError();		// Check for the '#!paco' header (security issue)	std::ifstream f(log().c_str());	string buf;	if (!(f && getline(f, buf) && buf.find("#!paco") == 0))		throw ConstructorError();		while (getline(f, buf) && buf.size() > 3 && buf[0] == '#' &&		buf[2] == ':') {		switch (buf[1]) {			case 'd':				mDate = str2num<int>(buf.substr(3));				break;			case '#':				sscanf(buf.c_str(), "##:%ld|%ld|%ld|%ld",					&mSizeInst, &mSizeMiss, &mFilesInst, &mFilesMiss);				break;			case 'c':				mConfOpts = buf.substr(3);				return;		}	}}// [virtual]BasePkg::~BasePkg(){	for (iterator f = begin(); f != end(); ++f) {		assert(*f != NULL);		if (*f) {			delete *f;			*f = NULL;		}	}}void BasePkg::getFiles(int type /* = ALL_FILES */){	clear();	string buf;	FileStream<std::ifstream> f(mLog);	// skip the header	while (getline(f, buf) && buf[0] == '#') ;	if (f.eof())		return;		char path[4096];	long raw, bz2, gz, s;		// Read files 	do {		if (UNLIKELY(4 != sscanf(buf.c_str(), "%[^|]|%ld|%ld|%ld",			path, &raw, &gz, &bz2))) {			goto ____parse_error;		}		switch (path[0]) {			case '/':				if (type & INSTALLED_FILES) {					if (raw != File::SIZEOF_MISSING)						push_back(new File(path, raw));					if (gz != File::SIZEOF_MISSING)						push_back(new File(string(path) + ".gz", gz));					if (bz2 != File::SIZEOF_MISSING)						push_back(new File(string(path) + ".bz2", bz2));				}				break;			case '-':				if (type & MISSING_FILES) {					s = (raw != File::SIZEOF_MISSING) ? raw : 0 +						(gz != File::SIZEOF_MISSING) ? gz : 0 +						(bz2 != File::SIZEOF_MISSING) ? bz2 : 0;					push_back(new File(&path[1], s, File::MISSING));				}				break;			default: ____parse_error:				throw X("Parse error while reading " + mLog					+ "\nRun 'paco -au' to update the database");		}	}	while (getline(f, buf));}bool BasePkg::hasFile(File* file){	sort();	return std::binary_search(begin(), end(), file, Sorter());}void BasePkg::sort(	SortType type,	// = SORT_NAME					bool reverse)	// = false{	// sort only if the list is not already sorted	if (mSortType != type) {		std::sort(begin(), end(), Sorter(type));		mSortType = type;	}	// reverse only if needed	if (mSortReverse != reverse) {		std::reverse(begin(), end());		mSortReverse = reverse;	}}//// Update the log file @log.// IMPORTANT: If return value is false it means that the log does not// exist or it was empty and it has been removed.//// [static]bool BasePkg::updateLog(string const& log){	if (access(log.c_str(), F_OK) < 0)		return false;	FileStream<std::ifstream> f(log);	string buf;	if (!(getline(f, buf) && !buf.find("#!paco")))		return true;	// header	std::ostringstream s;	while (getline(f, buf) && buf[0] == '#') {		if (buf.size() > 1 && buf[1] != '#')			s << buf << "\n";	}	if (f.eof()) {	// empty log (no logged files, only header)		unlink(log.c_str());		return false;	}		char* p;	char* file;	enum { RAW, GZ, BZ2, NSIZES };	long size[NSIZES], sizeInst = 0, sizeMiss = 0, filesInst = 0, filesMiss = 0; 		do {		if (UNLIKELY(!(file = strchr(buf.c_str(), '/'))))			continue;		else if ((p = strchr(file, '|')))			*p++ = 0;		if (getSize(size[RAW], file) +			getSize(size[GZ], file, ".gz") +			getSize(size[BZ2], file, ".bz2")) {			// installed file			s << file;			for (uint i = 0; i < NSIZES; ++i) {				s << "|" << size[i];				if (size[i] > 0)					sizeInst += size[i];			}			s << "\n";			filesInst++;		}		else if (p && LIKELY(3 == sscanf(p, "%ld|%ld|%ld",			&size[RAW], &size[GZ], &size[BZ2]))) {			// missing file			s << "-" << file;			for (uint i = 0; i < NSIZES; ++i) {				s << "|" << size[i];				if (size[i] > 0)					sizeMiss += size[i];			}			s << "\n";			filesMiss++;		}		else {			// missing file with unknown sizes			s << "-" << file << "|-2|-2|-2\n";			filesMiss++;		}	}	while (getline(f, buf));		f.close();	FileStream<std::ofstream> f2(log);	f2  << "#!paco-" PACKAGE_VERSION "\n##:" << sizeInst << "|" << sizeMiss		<< "|" << filesInst << "|" << filesMiss << "\n" << s.str();		return true;}// [static]bool BasePkg::getSize(long& size, string const& base, string const& suffix){	string path(base + suffix);	struct stat s;	if (lstat(path.c_str(), &s) < 0)		size = File::SIZEOF_MISSING;	else if (S_ISREG(s.st_mode)) {#if STATFS		struct STATFS f;#endif		int bsize;		if (BaseConfig::blockSize())			bsize = BaseConfig::blockSize();#if STATFS		else if (LIKELY(!STATFS(path.c_str(), &f) && (f.f_bsize > 0)))			bsize = f.f_bsize;#endif		else			bsize = s.st_blksize;		size = ((s.st_size / bsize) + ((s.st_size % bsize) > 0)) * bsize;	}	else if (S_ISLNK(s.st_mode))		size = File::SIZEOF_SYMLINK;		return (size != File::SIZEOF_MISSING);}//-----------------//// BasePkg::Sorter ////-----------------//BasePkg::Sorter::Sorter(SortType type /* = SORT_NAME */):	mSortFunc(type == SORT_NAME ? &Sorter::sortByName : &Sorter::sortBySize){ }inline bool BasePkg::Sorter::operator()(File* left, File* right) const{	return (this->*mSortFunc)(left, right);}inline bool BasePkg::Sorter::sortByName(File* left, File* right) const{	return left->name() > right->name();}inline bool BasePkg::Sorter::sortBySize(File* left, File* right) const{	return left->size() > right->size();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -