예제 #1
0
파일: DataStore.cpp 프로젝트: Myasuka/scidb
/* Clear all datastore files from the basepath
 */
void
DataStores::clearAllDataStores()
{
    /* Try to open the base dir
     */
    DIR* dirp = ::opendir(_basePath.c_str());

    if (dirp == NULL)
    {
        LOG4CXX_ERROR(logger, "DataStores::clearAllDataStores: failed to open base dir, aborting clearAll");
        return;
    }

    boost::function<int()> f = boost::bind(&File::closeDir, _basePath.c_str(), dirp, false);
    scidb::Destructor<boost::function<int()> >  dirCloser(f);

    struct dirent entry;
    memset(&entry, 0, sizeof(entry));

    /* For each entry in the base dir
     */
    while (true)
    {
        struct dirent *result(NULL);

        int rc = ::readdir_r(dirp, &entry, &result);
        if (rc != 0 || result == NULL)
        {
            return;
        }
        assert(result == &entry);

        LOG4CXX_TRACE(logger, "DataStores::clearAllDataStores: found entry " << entry.d_name);

        /* If its a datastore or fl file, go ahead and try to remove it
         */
        size_t entrylen = strlen(entry.d_name);
        size_t fllen = strlen(".fl");
        size_t datalen = strlen(".data");
        const char* entryend = entry.d_name + entrylen;

        /* Check if entry ends in ".fl" or ".data"
         */
        if (((entrylen > fllen) && 
             (strcmp(entryend - fllen, ".fl") == 0)) ||
            ((entrylen > datalen) &&
             (strcmp(entryend - datalen, ".data") == 0))
            )
        {
            LOG4CXX_TRACE(logger, "DataStores::clearAllDataStores: deleting entry " << entry.d_name);
            std::string fullpath = _basePath + "/" + entry.d_name;
            File::remove(fullpath.c_str(), false);
        }
    }
}
예제 #2
0
 /* Read the contents of a directory
  */
 void
 File::readDir(const char* dirName, std::list<std::string>& entries)
 {
     LOG4CXX_TRACE(logger, "File::readDir: " << dirName);
     
     DIR* dirp = ::opendir(dirName); // closedir
     
     if (dirp == NULL) {
         int err = errno;
     throw (SYSTEM_EXCEPTION(SCIDB_SE_INTERNAL, SCIDB_LE_SYSCALL_ERROR)
            << "opendir" << "NULL" << err << dirName);
     }
     
     boost::function<int()> f = boost::bind(&File::closeDir, dirName, dirp, false);
     scidb::Destructor<boost::function<int()> >  dirCloser(f);
     
     struct dirent entry;
     memset(&entry, 0, sizeof(entry));
     /*
      * See man readdir_r for the notes about struct dirent
      * On Linux, the assert should never fail.
      */
     assert((pathconf(dirName, _PC_NAME_MAX) + 1) == sizeof(entry.d_name));
     
     while (true) {
         
         struct dirent *result(NULL);
         
         int rc = ::readdir_r(dirp, &entry, &result);
         if (rc != 0) {
             int err = errno;
             throw (SYSTEM_EXCEPTION(SCIDB_SE_INTERNAL, SCIDB_LE_SYSCALL_ERROR)
                    << "readdir_r" << rc << err << dirName);
         }
         if (result == NULL) {
             // EOF
             return;
         }
         assert(result == &entry);
         
         entries.push_back(std::string(entry.d_name));
     }
 }
예제 #3
0
void
PackageWriter::_AddEntry(int dirFD, Entry* entry, const char* fileName)
{
printf("PackageWriter::_AddEntry(%d, %p, \"%s\")\n", dirFD, entry, fileName);
	bool isImplicitEntry = entry != NULL && entry->IsImplicit();

	// open the node
	int fd = openat(dirFD, fileName,
		O_RDONLY | (isImplicitEntry ? 0 : O_NOTRAVERSE));
	if (fd < 0) {
		fprintf(stderr, "Error: Failed to open entry \"%s\": %s\n",
			fileName, strerror(errno));
		throw status_t(errno);
	}
	FDCloser fdCloser(fd);

	// stat the node
	struct stat st;
	if (fstat(fd, &st) < 0) {
		fprintf(stderr, "Error: Failed to fstat() file \"%s\": %s\n",
			fileName, strerror(errno));
		throw status_t(errno);
	}

	// implicit entries must be directories
	if (isImplicitEntry && !S_ISDIR(st.st_mode)) {
		fprintf(stderr, "Error: Non-leaf path component \"%s\" is not a "
			"directory\n", fileName);
		throw status_t(B_BAD_VALUE);
	}

	// check/translate the node type
	uint8 fileType;
	uint32 defaultPermissions;
	if (S_ISREG(st.st_mode)) {
		fileType = B_HPKG_FILE_TYPE_FILE;
		defaultPermissions = B_HPKG_DEFAULT_FILE_PERMISSIONS;
	} else if (S_ISLNK(st.st_mode)) {
		fileType = B_HPKG_FILE_TYPE_SYMLINK;
		defaultPermissions = B_HPKG_DEFAULT_SYMLINK_PERMISSIONS;
	} else if (S_ISDIR(st.st_mode)) {
		fileType = B_HPKG_FILE_TYPE_DIRECTORY;
		defaultPermissions = B_HPKG_DEFAULT_DIRECTORY_PERMISSIONS;
	} else {
		// unsupported node type
		fprintf(stderr, "Error: Unsupported node type, entry: \"%s\"\n",
			fileName);
		throw status_t(B_UNSUPPORTED);
	}

	// add attribute entry
	Attribute* entryAttribute = _AddStringAttribute(
		B_HPKG_ATTRIBUTE_NAME_DIRECTORY_ENTRY, fileName);
	Stacker<Attribute> entryAttributeStacker(fTopAttribute, entryAttribute);

	// add stat data
	if (fileType != B_HPKG_DEFAULT_FILE_TYPE)
		_AddAttribute(B_HPKG_ATTRIBUTE_NAME_FILE_TYPE, fileType);
	if (defaultPermissions != uint32(st.st_mode & ALLPERMS)) {
		_AddAttribute(B_HPKG_ATTRIBUTE_NAME_FILE_PERMISSIONS,
			uint32(st.st_mode & ALLPERMS));
	}
	_AddAttribute(B_HPKG_ATTRIBUTE_NAME_FILE_ATIME, uint32(st.st_atime));
	_AddAttribute(B_HPKG_ATTRIBUTE_NAME_FILE_MTIME, uint32(st.st_mtime));
	_AddAttribute(B_HPKG_ATTRIBUTE_NAME_FILE_CRTIME, uint32(st.st_crtime));
	// TODO: File user/group!

	// add file data/symlink path
	if (S_ISREG(st.st_mode)) {
		// regular file -- add data
		if (st.st_size > 0) {
			FDDataReader dataReader(fd);
			status_t error = _AddData(dataReader, st.st_size);
			if (error != B_OK)
				throw status_t(error);
		}
	} else if (S_ISLNK(st.st_mode)) {
		// symlink -- add link address
		char path[B_PATH_NAME_LENGTH + 1];
		ssize_t bytesRead = readlinkat(dirFD, fileName, path,
			B_PATH_NAME_LENGTH);
		if (bytesRead < 0) {
			fprintf(stderr, "Error: Failed to read symlink \"%s\": %s\n",
				fileName, strerror(errno));
			throw status_t(errno);
		}

		path[bytesRead] = '\0';
		_AddStringAttribute(B_HPKG_ATTRIBUTE_NAME_SYMLINK_PATH, path);
	}

	// add attributes
	if (DIR* attrDir = fs_fopen_attr_dir(fd)) {
		CObjectDeleter<DIR, int> attrDirCloser(attrDir, fs_close_attr_dir);

		while (dirent* entry = readdir(attrDir)) {
			attr_info attrInfo;
			if (fs_stat_attr(fd, entry->d_name, &attrInfo) < 0) {
				fprintf(stderr, "Error: Failed to stat attribute \"%s\" of "
					"file \"%s\": %s\n", entry->d_name, fileName,
					strerror(errno));
				throw status_t(errno);
			}

			// create attribute entry
			Attribute* attributeAttribute = _AddStringAttribute(
				B_HPKG_ATTRIBUTE_NAME_FILE_ATTRIBUTE, entry->d_name);
			Stacker<Attribute> attributeAttributeStacker(fTopAttribute,
				attributeAttribute);

			// add type
			_AddAttribute(B_HPKG_ATTRIBUTE_NAME_FILE_ATTRIBUTE_TYPE,
				(uint32)attrInfo.type);

			// add data
			AttributeDataReader dataReader(fd, entry->d_name, attrInfo.type);
			status_t error = _AddData(dataReader, attrInfo.size);
			if (error != B_OK)
				throw status_t(error);
		}
	}

	if (S_ISDIR(st.st_mode)) {
		// directory -- recursively add children
		if (isImplicitEntry) {
			// this is an implicit entry -- just add it's children
			for (EntryList::ConstIterator it = entry->ChildIterator();
					Entry* child = it.Next();) {
				_AddEntry(fd, child, child->Name());
			}
		} else {
			// we need to clone the directory FD for fdopendir()
			int clonedFD = dup(fd);
			if (clonedFD < 0) {
				fprintf(stderr, "Error: Failed to dup() directory FD: %s\n",
					strerror(errno));
				throw status_t(errno);
			}

			DIR* dir = fdopendir(clonedFD);
			if (dir == NULL) {
				fprintf(stderr, "Error: Failed to open directory \"%s\": %s\n",
					fileName, strerror(errno));
				close(clonedFD);
				throw status_t(errno);
			}
			CObjectDeleter<DIR, int> dirCloser(dir, closedir);

			while (dirent* entry = readdir(dir)) {
				// skip "." and ".."
				if (strcmp(entry->d_name, ".") == 0
					|| strcmp(entry->d_name, "..") == 0) {
					continue;
				}

				_AddEntry(fd, NULL, entry->d_name);
			}
		}
	}
}