1/* 2 * Copyright 2002-2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Tyler Dauwalder 7 * Ingo Weinhold, bonefish@users.sf.net 8 */ 9 10/*! 11 \file MimeUpdateThread.cpp 12 MimeUpdateThread implementation 13*/ 14 15#include <stdio.h> 16 17#include <Directory.h> 18#include <Message.h> 19#include <Path.h> 20#include <RegistrarDefs.h> 21#include <Volume.h> 22 23#include <storage_support.h> 24#include "mime/MimeUpdateThread.h" 25 26//#define DBG(x) x 27#define DBG(x) 28#define OUT printf 29 30 31namespace BPrivate { 32namespace Storage { 33 34#if (defined(__BEOS__) || defined(__HAIKU__)) 35// device_is_root_device 36bool 37device_is_root_device(dev_t device) 38{ 39 return device == 1; 40} 41#endif 42 43namespace Mime { 44 45/*! \class MimeUpdateThread 46 \brief RegistrarThread class implementing the common functionality of 47 update_mime_info() and create_app_meta_mime() 48*/ 49 50// constructor 51/*! \brief Creates a new MimeUpdateThread object. 52 53 If \a replyee is non-NULL and construction succeeds, the MimeThreadObject 54 assumes resposibility for its deletion. 55 56 Also, if \c non-NULL, \a replyee is expected to be a \c B_REG_MIME_UPDATE_MIME_INFO 57 or a \c B_REG_MIME_CREATE_APP_META_MIME message with a \c true \c "synchronous" 58 field detached from the registrar's mime manager looper (though this is not verified). 59 The message will be replied to at the end of the thread's execution. 60*/ 61MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, 62 BMessenger managerMessenger, const entry_ref *root, bool recursive, 63 int32 force, BMessage *replyee) 64 : /*RegistrarThread(name, priority, managerMessenger) 65 ,*/ fRoot(root ? *root : entry_ref()) 66 , fRecursive(recursive) 67 , fForce(force) 68 , fReplyee(replyee) 69 , fStatus(root ? B_OK : B_BAD_VALUE) 70{ 71} 72 73// destructor 74/*! \brief Destroys the MimeUpdateThread object. 75 76 If the object was properly initialized (i.e. InitCheck() returns \c B_OK) and 77 the replyee message passed to the constructor was \c non-NULL, the replyee 78 message is deleted. 79*/ 80MimeUpdateThread::~MimeUpdateThread() 81{ 82 // delete our acquired BMessage 83 if (InitCheck() == B_OK) 84 delete fReplyee; 85} 86 87// InitCheck() 88/*! \brief Returns the initialization status of the object 89*/ 90status_t 91MimeUpdateThread::InitCheck() 92{ 93 return fStatus; 94} 95 96// ThreadFunction 97/*! \brief Implements the common functionality of update_mime_info() and 98 create_app_meta_mime(), namely iterating through the filesystem and 99 updating entries. 100*/ 101status_t 102MimeUpdateThread::ThreadFunction() 103{ 104 status_t err = InitCheck(); 105 // Do the updates 106 if (!err) 107 err = UpdateEntry(&fRoot); 108/* // Send a reply if we have a message to reply to 109 if (fReplyee) { 110 BMessage reply(B_REG_RESULT); 111 status_t error = reply.AddInt32("result", err); 112 err = error; 113 if (!err) 114 err = fReplyee->SendReply(&reply); 115 } 116 // Flag ourselves as finished 117 fIsFinished = true; 118 // Notify the thread manager to make a cleanup run 119 if (!err) { 120 BMessage msg(B_REG_MIME_UPDATE_THREAD_FINISHED); 121 status_t error = fManagerMessenger.SendMessage(&msg, (BHandler*)NULL, 500000); 122 if (error) 123 OUT("WARNING: ThreadManager::ThreadEntryFunction(): Termination notification " 124 "failed with error 0x%lx\n", error); 125 } 126 DBG(OUT("(id: %ld) exiting mime update thread with result 0x%lx\n", 127 find_thread(NULL), err)); 128*/ return err; 129} 130 131// DeviceSupportsAttributes 132/*! \brief Returns true if the given device supports attributes, false 133 if not (or if an error occurs while determining). 134 135 Device numbers and their corresponding support info are cached in 136 a std::list to save unnecessarily \c statvfs()ing devices that have 137 already been statvfs()ed (which might otherwise happen quite often 138 for a device that did in fact support attributes). 139 140 \return 141 - \c true: The device supports attributes 142 - \c false: The device does not support attributes, or there was an 143 error while determining 144*/ 145bool 146MimeUpdateThread::DeviceSupportsAttributes(dev_t device) 147{ 148 return true; 149} 150 151// UpdateEntry 152/*! \brief Updates the given entry and then recursively updates all the entry's child 153 entries if the entry is a directory and \c fRecursive is true. 154*/ 155status_t 156MimeUpdateThread::UpdateEntry(const entry_ref *ref) 157{ 158 status_t err = ref ? B_OK : B_BAD_VALUE; 159 bool entryIsDir = false; 160 161 // Look to see if we're being terminated 162// if (!err && fShouldExit) 163// err = B_CANCELED; 164 165 // Before we update, make sure this entry lives on a device that supports 166 // attributes. If not, we skip it and any of its children for 167 // updates (we don't signal an error, however). 168 169//BPath path(ref); 170//printf("Updating '%s' (%s)... \n", path.Path(), 171// (DeviceSupportsAttributes(ref->device) ? "yes" : "no")); 172 173 if (!err 174 && (device_is_root_device(ref->device) 175 || DeviceSupportsAttributes(ref->device))) { 176 // Update this entry 177 if (!err) 178 err = DoMimeUpdate(ref, &entryIsDir); 179 180 // If we're recursing and this is a directory, update 181 // each of the directory's children as well 182 if (!err && fRecursive && entryIsDir) { 183 BDirectory dir; 184 err = dir.SetTo(ref); 185 if (!err) { 186 entry_ref childRef; 187 while (!err) { 188 err = dir.GetNextRef(&childRef); 189 if (err) { 190 // If we've come to the end of the directory listing, 191 // it's not an error. 192 if (err == B_ENTRY_NOT_FOUND) 193 err = B_OK; 194 break; 195 } else { 196 err = UpdateEntry(&childRef); 197 } 198 } 199 } 200 } 201 } 202 return err; 203} 204 205} // namespace Mime 206} // namespace Storage 207} // namespace BPrivate 208