/* 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); } } }
/* 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)); } }
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); } } } }