Updated filesystem traversal code to skip files/devices that don't

support attributes.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1325 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2002-10-01 07:26:11 +00:00
parent ef3fb6465d
commit 09dad369d7
2 changed files with 94 additions and 29 deletions
headers/private/storage/mime
src/kits/storage/mime

@ -14,6 +14,9 @@
#include <RegistrarThread.h>
#include <SupportDefs.h>
#include <list>
#include <pair.h>
struct entry_ref;
class BMessage;
@ -37,8 +40,12 @@ protected:
const bool fRecursive;
const bool fForce;
BMessage *fReplyee;
bool DeviceSupportsAttributes(dev_t device);
private:
std::list< std::pair<dev_t, bool> > fAttributeSupportList;
status_t UpdateEntry(const entry_ref *ref);
status_t fStatus;

@ -10,9 +10,11 @@
#include "mime/MimeUpdateThread.h"
#include <Directory.h>
#include <kernel_interface.h>
#include <Message.h>
#include <Path.h>
#include <RegistrarDefs.h>
#include <Volume.h>
#include <stdio.h>
@ -60,6 +62,7 @@ MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, BMessenger
*/
MimeUpdateThread::~MimeUpdateThread()
{
// delete our acquired BMessage
if (InitCheck() == B_OK)
delete fReplyee;
}
@ -110,6 +113,53 @@ MimeUpdateThread::ThreadFunction()
find_thread(NULL), err));
}
// DeviceSupportsAttributes
/*! \brief Returns true if the given device supports attributes, false
if not (or if an error occurs while determining).
Device numbers and their corresponding support info are cached in
a std::list to save unnecessarily \c statvfs()ing devices that have
already been statvfs()ed (which might otherwise happen quite often
for a device that did in fact support attributes).
\return
- \c true: The device supports attributes
- \c false: The device does not support attributes, or there was an
error while determining
*/
bool
MimeUpdateThread::DeviceSupportsAttributes(dev_t device)
{
// See if an entry for this device already exists
std::list< std::pair<dev_t,bool> >::iterator i;
for (i = fAttributeSupportList.begin();
i != fAttributeSupportList.end();
i++)
{
if (i->first == device)
return i->second;
}
bool result = false;
// If we get here, no such device is yet in our list,
// so we attempt to remedy the situation
BVolume volume;
status_t err = volume.SetTo(device);
if (!err) {
result = volume.KnowsAttr();
// devices supporting attributes are likely to be queried
// again, devices not supporting attributes are not
std::pair<dev_t,bool> p(device, result);
if (result)
fAttributeSupportList.push_front(p);
else
fAttributeSupportList.push_back(p);
}
return result;
}
// UpdateEntry
/*! \brief Updates the given entry and then recursively updates all the entry's child
entries if the entry is a directory and \c fRecursive is true.
@ -120,39 +170,47 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref)
status_t err = ref ? B_OK : B_BAD_VALUE;
bool entryIsDir = false;
// Update this entry
if (!err) {
DoMimeUpdate(ref, &entryIsDir);
// err = DoMimeUpdate(ref, &entryIsDir);
/* BPath path(ref);
printf("Updating '%s'... ", path.Path());
fflush(stdout);
printf("0x%lx\n", DoMimeUpdate(ref, &entryIsDir));
*/
}
// Look to see if we're being terminated
if (!err && fShouldExit)
err = B_CANCELED;
// If we're recursing and this is a directory, update
// each of the directory's children as well
if (!err && fRecursive && entryIsDir) {
BDirectory dir;
err = dir.SetTo(ref);
// Before we update, make sure this entry lives on a device that supports
// attributes. If not, we skip it and any of its children for
// updates (we don't signal an error, however).
//BPath path(ref);
//printf("Updating '%s' (%s)... \n", path.Path(),
// (DeviceSupportsAttributes(ref->device) ? "yes" : "no"));
if (!err
&& (device_is_root_device(ref->device)
|| DeviceSupportsAttributes(ref->device))) {
// Update this entry
if (!err) {
entry_ref childRef;
while (!err) {
err = dir.GetNextRef(&childRef);
if (err) {
// If we've come to the end of the directory listing,
// it's not an error.
if (err == B_ENTRY_NOT_FOUND)
err = B_OK;
break;
} else {
err = UpdateEntry(&childRef);
}
}
}
// R5 appears to ignore whether or not the update succeeds.
DoMimeUpdate(ref, &entryIsDir);
}
// If we're recursing and this is a directory, update
// each of the directory's children as well
if (!err && fRecursive && entryIsDir) {
BDirectory dir;
err = dir.SetTo(ref);
if (!err) {
entry_ref childRef;
while (!err) {
err = dir.GetNextRef(&childRef);
if (err) {
// If we've come to the end of the directory listing,
// it's not an error.
if (err == B_ENTRY_NOT_FOUND)
err = B_OK;
break;
} else {
err = UpdateEntry(&childRef);
}
}
}
}
}
return err;
}