xref: /haiku/src/build/libbe/storage/NodeInfo.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 //----------------------------------------------------------------------
2 //  This software is part of the Haiku distribution and is covered
3 //  by the MIT license.
4 //---------------------------------------------------------------------
5 /*!
6 	\file NodeInfo.cpp
7 	BNodeInfo implementation.
8 */
9 
10 #include <NodeInfo.h>
11 
12 #include <new>
13 #include <string.h>
14 
15 #include <MimeTypes.h>
16 #include <Bitmap.h>
17 #include <Entry.h>
18 #include <Node.h>
19 #include <Path.h>
20 #include <Rect.h>
21 
22 #include <fs_attr.h>
23 #include <fs_info.h>
24 
25 using namespace std;
26 
27 // attribute names
28 #define NI_BEOS "BEOS"
29 static const char *kNITypeAttribute			= NI_BEOS ":TYPE";
30 static const char *kNIPreferredAppAttribute	= NI_BEOS ":PREF_APP";
31 static const char *kNIAppHintAttribute		= NI_BEOS ":PPATH";
32 static const char *kNIMiniIconAttribute		= NI_BEOS ":M:STD_ICON";
33 static const char *kNILargeIconAttribute	= NI_BEOS ":L:STD_ICON";
34 
35 // icon types
36 enum {
37 	B_MINI_ICON_TYPE	= 'MICN',
38 	B_LARGE_ICON_TYPE	= 'ICON',
39 };
40 
41 // constructor
42 /*!	\brief Creates an uninitialized BNodeInfo object.
43 
44 	After created a BNodeInfo with this, you should call SetTo().
45 
46 	\see SetTo(BNode *node)
47 */
48 BNodeInfo::BNodeInfo()
49 		 : fNode(NULL),
50 		   fCStatus(B_NO_INIT)
51 {
52 }
53 
54 // constructor
55 /*!	\brief Creates a BNodeInfo object and initializes it to the supplied node.
56 
57 	\param node The node to gather information on. Can be any flavor.
58 
59 	\see SetTo(BNode *node)
60 */
61 BNodeInfo::BNodeInfo(BNode *node)
62 		 : fNode(NULL),
63 		   fCStatus(B_NO_INIT)
64 {
65 	fCStatus = SetTo(node);
66 }
67 
68 // destructor
69 /*!	\brief Frees all resources associated with this object.
70 
71 	The BNode object passed to the constructor or to SetTo() is not deleted.
72 */
73 BNodeInfo::~BNodeInfo()
74 {
75 }
76 
77 // SetTo
78 /*!	\brief Initializes the BNodeInfo to the supplied node.
79 
80 	The BNodeInfo object does not copy the supplied object, but uses it
81 	directly. You must not delete the object you supply while the BNodeInfo
82 	does exist. The BNodeInfo does not take over ownership of the BNode and
83 	it doesn't delete it on destruction.
84 
85 	\param node The node to play with
86 
87 	\return
88 	- \c B_OK: Everything went fine.
89 	- \c B_BAD_VALUE: The node was bad.
90 */
91 status_t
92 BNodeInfo::SetTo(BNode *node)
93 {
94 	fNode = NULL;
95 	// check parameter
96 	fCStatus = (node && node->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
97 	if (fCStatus == B_OK)
98 		fNode = node;
99 	return fCStatus;
100 }
101 
102 // InitCheck
103 /*!	\brief returns whether the object has been properly initialized.
104 
105 	\return
106 	- \c B_OK: Everything went fine.
107 	- \c B_NO_INIT: The node is not properly initialized.
108 */
109 status_t
110 BNodeInfo::InitCheck() const
111 {
112 	return fCStatus;
113 }
114 
115 // GetType
116 /*!	\brief Gets the node's MIME type.
117 
118 	Writes the contents of the "BEOS:TYPE" attribute into the supplied buffer
119 	\a type.
120 
121 	\param type A pointer to a pre-allocated character buffer of size
122 		   \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the
123 		   node shall be written.
124 	\return
125 	- \c B_OK: Everything went fine.
126 	- \c B_NO_INIT: The object is not properly initialized.
127 	- \c B_BAD_VALUE: \c NULL \a type or the type string stored in the
128 	  attribute is longer than \c B_MIME_TYPE_LENGTH.
129 	- \c B_BAD_TYPE: The attribute the type string is stored in has the wrong
130 	   type.
131 	- \c B_ENTRY_NOT_FOUND: No type is set on the node.
132 	- other error codes
133 */
134 status_t
135 BNodeInfo::GetType(char *type) const
136 {
137 	// check parameter and initialization
138 	status_t error = (type ? B_OK : B_BAD_VALUE);
139 	if (error == B_OK && InitCheck() != B_OK)
140 		error = B_NO_INIT;
141 	// get the attribute info and check type and length of the attr contents
142 	attr_info attrInfo;
143 	if (error == B_OK)
144 		error = fNode->GetAttrInfo(kNITypeAttribute, &attrInfo);
145 	if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
146 		error = B_BAD_TYPE;
147 	if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH)
148 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
149 	// read the data
150 	if (error == B_OK) {
151 		ssize_t read = fNode->ReadAttr(kNITypeAttribute, attrInfo.type, 0,
152 									   type, attrInfo.size);
153 		if (read < 0)
154 			error = read;
155 		else if (read != attrInfo.size)
156 			error = B_ERROR;
157 		// to be save, null terminate the string at the very end
158 		if (error == B_OK)
159 			type[B_MIME_TYPE_LENGTH - 1] = '\0';
160 	}
161 	return error;
162 }
163 
164 // SetType
165 /*!	\brief Sets the node's MIME type.
166 
167 	The supplied string is written into the node's "BEOS:TYPE" attribute.
168 
169 	If \a type is \c NULL, the respective attribute is removed.
170 
171 	\param type The MIME type to be assigned to the node. Must not be longer
172 		   than \c B_MIME_TYPE_LENGTH (including the terminating null).
173 		   May be \c NULL.
174 	\return
175 	- \c B_OK: Everything went fine.
176 	- \c B_NO_INIT: The object is not properly initialized.
177 	- \c B_BAD_VALUE: \a type is longer than \c B_MIME_TYPE_LENGTH.
178 	- other error codes
179 */
180 status_t
181 BNodeInfo::SetType(const char *type)
182 {
183 	// check parameter and initialization
184 	status_t error = B_OK;
185 	if (error == B_OK && type && strlen(type) >= B_MIME_TYPE_LENGTH)
186 		error = B_BAD_VALUE;
187 	if (error == B_OK && InitCheck() != B_OK)
188 		error = B_NO_INIT;
189 	// write/remove the attribute
190 	if (error == B_OK) {
191 		if (type) {
192 			size_t toWrite = strlen(type) + 1;
193 			ssize_t written = fNode->WriteAttr(kNITypeAttribute,
194 											   B_MIME_STRING_TYPE, 0, type,
195 											   toWrite);
196 			if (written < 0)
197 				error = written;
198 			else if (written != (ssize_t)toWrite)
199 				error = B_ERROR;
200 		} else
201 			error = fNode->RemoveAttr(kNITypeAttribute);
202 	}
203 	return error;
204 }
205 
206 // GetIcon
207 /*!	\brief Gets the node's icon.
208 
209 	The icon stored in the node's "BEOS:L:STD_ICON" (large) or
210 	"BEOS:M:STD_ICON" (mini) attribute is retrieved.
211 
212 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
213 		   to store the requested icon (16x16 for the mini and 32x32 for the
214 		   large icon).
215 	\param k Specifies the size of the icon to be retrieved: \c B_MINI_ICON
216 		   for the mini and \c B_LARGE_ICON for the large icon.
217 	\return
218 	- \c B_OK: Everything went fine.
219 	- \c B_NO_INIT: The object is not properly initialized.
220 	- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a k or bitmap
221 		 dimensions (\a icon) and icon size (\a k) do not match.
222 	- other error codes
223 */
224 status_t
225 BNodeInfo::GetIcon(BBitmap *icon, icon_size k) const
226 {
227 	status_t error = B_OK;
228 	// set some icon size related variables
229 	const char *attribute = NULL;
230 	BRect bounds;
231 	uint32 attrType = 0;
232 	size_t attrSize = 0;
233 	switch (k) {
234 		case B_MINI_ICON:
235 			attribute = kNIMiniIconAttribute;
236 			bounds.Set(0, 0, 15, 15);
237 			attrType = B_MINI_ICON_TYPE;
238 			attrSize = 16 * 16;
239 			break;
240 		case B_LARGE_ICON:
241 			attribute = kNILargeIconAttribute;
242 			bounds.Set(0, 0, 31, 31);
243 			attrType = B_LARGE_ICON_TYPE;
244 			attrSize = 32 * 32;
245 			break;
246 		default:
247 			error = B_BAD_VALUE;
248 			break;
249 	}
250 	// check parameter and initialization
251 	if (error == B_OK
252 		&& (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
253 		error = B_BAD_VALUE;
254 	}
255 	if (error == B_OK && InitCheck() != B_OK)
256 		error = B_NO_INIT;
257 	// get the attribute info and check type and size of the attr contents
258 	attr_info attrInfo;
259 	if (error == B_OK)
260 		error = fNode->GetAttrInfo(attribute, &attrInfo);
261 	if (error == B_OK && attrInfo.type != attrType)
262 		error = B_BAD_TYPE;
263 	if (error == B_OK && attrInfo.size != attrSize)
264 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
265 	// read the attribute
266 	if (error == B_OK) {
267 		bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
268 		char *buffer = NULL;
269 		ssize_t read;
270 		if (otherColorSpace) {
271 			// other color space than stored in attribute
272 			buffer = new(nothrow) char[attrSize];
273 			if (!buffer)
274 				error = B_NO_MEMORY;
275 			if (error == B_OK) {
276 				read = fNode->ReadAttr(attribute, attrType, 0, buffer,
277 									   attrSize);
278 			}
279 		} else {
280 			read = fNode->ReadAttr(attribute, attrType, 0, icon->Bits(),
281 								   attrSize);
282 		}
283 		if (error == B_OK) {
284 			if (read < 0)
285 				error = read;
286 			else if (read != attrInfo.size)
287 				error = B_ERROR;
288 		}
289 		if (otherColorSpace) {
290 			// other color space than stored in attribute
291 			if (error == B_OK) {
292 				error = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
293 										 0, B_CMAP8);
294 			}
295 			delete[] buffer;
296 		}
297 	}
298 	return error;
299 }
300 
301 // SetIcon
302 /*!	\brief Sets the node's icon.
303 
304 	The icon is stored in the node's "BEOS:L:STD_ICON" (large) or
305 	"BEOS:M:STD_ICON" (mini) attribute.
306 
307 	If \a icon is \c NULL, the respective attribute is removed.
308 
309 	\param icon A pointer to the BBitmap containing the icon to be set.
310 		   May be \c NULL.
311 	\param k Specifies the size of the icon to be set: \c B_MINI_ICON
312 		   for the mini and \c B_LARGE_ICON for the large icon.
313 	\return
314 	- \c B_OK: Everything went fine.
315 	- \c B_NO_INIT: The object is not properly initialized.
316 	- \c B_BAD_VALUE: Unknown icon size \a k or bitmap dimensions (\a icon)
317 		 and icon size (\a k) do not match.
318 	- other error codes
319 */
320 status_t
321 BNodeInfo::SetIcon(const BBitmap *icon, icon_size k)
322 {
323 	status_t error = B_OK;
324 	// set some icon size related variables
325 	const char *attribute = NULL;
326 	BRect bounds;
327 	uint32 attrType = 0;
328 	size_t attrSize = 0;
329 	switch (k) {
330 		case B_MINI_ICON:
331 			attribute = kNIMiniIconAttribute;
332 			bounds.Set(0, 0, 15, 15);
333 			attrType = B_MINI_ICON_TYPE;
334 			attrSize = 16 * 16;
335 			break;
336 		case B_LARGE_ICON:
337 			attribute = kNILargeIconAttribute;
338 			bounds.Set(0, 0, 31, 31);
339 			attrType = B_LARGE_ICON_TYPE;
340 			attrSize = 32 * 32;
341 			break;
342 		default:
343 			error = B_BAD_VALUE;
344 			break;
345 	}
346 	// check parameter and initialization
347 	if (error == B_OK && icon
348 		&& (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
349 		error = B_BAD_VALUE;
350 	}
351 	if (error == B_OK && InitCheck() != B_OK)
352 		error = B_NO_INIT;
353 	// write/remove the attribute
354 	if (error == B_OK) {
355 		if (icon) {
356 			bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
357 			ssize_t written = 0;
358 			if (otherColorSpace) {
359 				BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8);
360 				error = bitmap.InitCheck();
361 				if (error == B_OK)
362 					error = bitmap.ImportBits(icon);
363 				if (error == B_OK) {
364 					written = fNode->WriteAttr(attribute, attrType, 0,
365 											   bitmap.Bits(), attrSize);
366 				}
367 			} else {
368 				written = fNode->WriteAttr(attribute, attrType, 0,
369 										   icon->Bits(), attrSize);
370 			}
371 			if (error == B_OK) {
372 				if (written < 0)
373 					error = written;
374 				else if (written != (ssize_t)attrSize)
375 					error = B_ERROR;
376 			}
377 		} else	// no icon given => remove
378 			error = fNode->RemoveAttr(attribute);
379 	}
380 	return error;
381 }
382 
383 // GetPreferredApp
384 /*!	\brief Gets the node's preferred application.
385 
386 	Writes the contents of the "BEOS:PREF_APP" attribute into the supplied
387 	buffer \a signature. The preferred application is identifief by its
388 	signature.
389 
390 	\param signature A pointer to a pre-allocated character buffer of size
391 		   \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the
392 		   preferred application shall be written.
393 	\param verb Specifies the type of access the preferred application is
394 		   requested for. Currently only \c B_OPEN is meaningful.
395 	\return
396 	- \c B_OK: Everything went fine.
397 	- \c B_NO_INIT: The object is not properly initialized.
398 	- \c B_BAD_VALUE: \c NULL \a signature or bad app_verb \a verb.
399 	- other error codes
400 */
401 status_t
402 BNodeInfo::GetPreferredApp(char *signature, app_verb verb) const
403 {
404 	// check parameter and initialization
405 	status_t error = (signature && verb == B_OPEN ? B_OK : B_BAD_VALUE);
406 	if (error == B_OK && InitCheck() != B_OK)
407 		error = B_NO_INIT;
408 	// get the attribute info and check type and length of the attr contents
409 	attr_info attrInfo;
410 	if (error == B_OK)
411 		error = fNode->GetAttrInfo(kNIPreferredAppAttribute, &attrInfo);
412 	if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
413 		error = B_BAD_TYPE;
414 	if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH)
415 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
416 	// read the data
417 	if (error == B_OK) {
418 		ssize_t read = fNode->ReadAttr(kNIPreferredAppAttribute, attrInfo.type,
419 									   0, signature, attrInfo.size);
420 		if (read < 0)
421 			error = read;
422 		else if (read != attrInfo.size)
423 			error = B_ERROR;
424 		// to be save, null terminate the string at the very end
425 		if (error == B_OK)
426 			signature[B_MIME_TYPE_LENGTH - 1] = '\0';
427 	}
428 	return error;
429 }
430 
431 // SetPreferredApp
432 /*!	\brief Sets the node's preferred application.
433 
434 	The supplied string is written into the node's "BEOS:PREF_APP" attribute.
435 
436 	If \a signature is \c NULL, the respective attribute is removed.
437 
438 	\param signature The signature of the preferred application to be set.
439 		   Must not be longer than \c B_MIME_TYPE_LENGTH (including the
440 		   terminating null). May be \c NULL.
441 	\param verb Specifies the type of access the preferred application shall
442 		   be set for. Currently only \c B_OPEN is meaningful.
443 	\return
444 	- \c B_OK: Everything went fine.
445 	- \c B_NO_INIT: The object is not properly initialized.
446 	- \c B_BAD_VALUE: \c NULL \a signature, \a signature is longer than
447 	  \c B_MIME_TYPE_LENGTH or bad app_verb \a verb.
448 	- other error codes
449 */
450 status_t
451 BNodeInfo::SetPreferredApp(const char *signature, app_verb verb)
452 {
453 	// check parameters and initialization
454 	status_t error = (verb == B_OPEN ? B_OK : B_BAD_VALUE);
455 	if (error == B_OK && signature && strlen(signature) >= B_MIME_TYPE_LENGTH)
456 		error = B_BAD_VALUE;
457 	if (error == B_OK && InitCheck() != B_OK)
458 		error = B_NO_INIT;
459 	// write/remove the attribute
460 	if (error == B_OK) {
461 		if (signature) {
462 			size_t toWrite = strlen(signature) + 1;
463 			ssize_t written = fNode->WriteAttr(kNIPreferredAppAttribute,
464 											   B_MIME_STRING_TYPE, 0,
465 											   signature, toWrite);
466 			if (written < 0)
467 				error = written;
468 			else if (written != (ssize_t)toWrite)
469 				error = B_ERROR;
470 		} else
471 			error = fNode->RemoveAttr(kNIPreferredAppAttribute);
472 	}
473 	return error;
474 }
475 
476 // GetAppHint
477 /*!	\brief Returns a hint in form of and entry_ref to the application that
478 		   shall be used to open this node.
479 
480 	The path contained in the node's "BEOS:PPATH" attribute is converted into
481 	an entry_ref and returned in \a ref.
482 
483 	\param ref A pointer to a pre-allocated entry_ref into which the requested
484 		   app hint shall be written.
485 	\return
486 	- \c B_OK: Everything went fine.
487 	- \c B_NO_INIT: The object is not properly initialized.
488 	- \c B_BAD_VALUE: \c NULL \a ref.
489 	- other error codes
490 */
491 status_t
492 BNodeInfo::GetAppHint(entry_ref *ref) const
493 {
494 	// check parameter and initialization
495 	status_t error = (ref ? B_OK : B_BAD_VALUE);
496 	if (error == B_OK && InitCheck() != B_OK)
497 		error = B_NO_INIT;
498 	// get the attribute info and check type and length of the attr contents
499 	attr_info attrInfo;
500 	if (error == B_OK)
501 		error = fNode->GetAttrInfo(kNIAppHintAttribute, &attrInfo);
502 	// NOTE: The attribute type should be B_STRING_TYPE, but R5 uses
503 	// B_MIME_STRING_TYPE.
504 	if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
505 		error = B_BAD_TYPE;
506 	if (error == B_OK && attrInfo.size > B_PATH_NAME_LENGTH)
507 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
508 	// read the data
509 	if (error == B_OK) {
510 		char path[B_PATH_NAME_LENGTH];
511 		ssize_t read = fNode->ReadAttr(kNIAppHintAttribute, attrInfo.type, 0,
512 									   path, attrInfo.size);
513 		if (read < 0)
514 			error = read;
515 		else if (read != attrInfo.size)
516 			error = B_ERROR;
517 		// get the entry_ref for the path
518 		if (error == B_OK) {
519 			// to be save, null terminate the path at the very end
520 			path[B_PATH_NAME_LENGTH - 1] = '\0';
521 			error = get_ref_for_path(path, ref);
522 		}
523 	}
524 	return error;
525 }
526 
527 // SetAppHint
528 /*!	\brief Sets the node's app hint.
529 
530 	The supplied entry_ref is converted into a path and stored in the node's
531 	"BEOS:PPATH" attribute.
532 
533 	If \a ref is \c NULL, the respective attribute is removed.
534 
535 	\param ref A pointer to an entry_ref referring to the application.
536 		   May be \c NULL.
537 	\return
538 	- \c B_OK: Everything went fine.
539 	- \c B_NO_INIT: The object is not properly initialized.
540 	- \c B_BAD_VALUE: \c NULL \a ref.
541 	- other error codes
542 */
543 status_t
544 BNodeInfo::SetAppHint(const entry_ref *ref)
545 {
546 	// check parameter and initialization
547 	status_t error = B_OK;
548 	if (error == B_OK && InitCheck() != B_OK)
549 		error = B_NO_INIT;
550 	// write/remove the attribute
551 	if (error == B_OK) {
552 		if (ref) {
553 			BPath path;
554 			error = path.SetTo(ref);
555 			if (error == B_OK) {
556 				size_t toWrite = strlen(path.Path()) + 1;
557 				ssize_t written = fNode->WriteAttr(kNIAppHintAttribute,
558 												   B_MIME_STRING_TYPE, 0,
559 												   path.Path(), toWrite);
560 				if (written < 0)
561 					error = written;
562 				else if (written != (ssize_t)toWrite)
563 					error = B_ERROR;
564 			}
565 		} else
566 			error = fNode->RemoveAttr(kNIAppHintAttribute);
567 	}
568 	return error;
569 }
570 
571 // GetTrackerIcon
572 /*!	\brief Gets the icon which tracker displays.
573 
574 	This method tries real hard to find an icon for the node:
575 	- If the node has no type, return the icon for B_FILE_MIME_TYPE if it's a
576 	  regular file, for B_DIRECTORY_MIME_TYPE if it's a directory, etc. from
577 	  the MIME database. Even, if the node has an own icon!
578 	- Ask GetIcon().
579 	- Get the preferred application and ask the MIME database, if that
580 	  application has a special icon for the node's file type.
581 	- Ask the MIME database whether there is an icon for the node's file type.
582 	- Ask the MIME database for the preferred application for the node's
583 	  file type and whether this application has a special icon for the type.
584 	- Return the icon for whatever type of node (file/dir/etc.) from the MIME database.
585 	This list is processed in the given order and the icon the first
586 	successful attempt provides is returned. In case none of them yields an
587 	icon, this method fails. This is very unlikely though.
588 
589 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
590 		   to store the requested icon (16x16 for the mini and 32x32 for the
591 		   large icon).
592 	\param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON
593 		   for the mini and \c B_LARGE_ICON for the large icon.
594 	\return
595 	- \c B_OK: Everything went fine.
596 	- \c B_NO_INIT: The object is not properly initialized.
597 	- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a iconSize or bitmap
598 		 dimensions (\a icon) and icon size (\a iconSize) do not match.
599 	- other error codes
600 */
601 status_t
602 BNodeInfo::GetTrackerIcon(BBitmap *icon, icon_size iconSize) const
603 {
604 	// set some icon size related variables
605 	status_t error = B_OK;
606 	BRect bounds;
607 	switch (iconSize) {
608 		case B_MINI_ICON:
609 			bounds.Set(0, 0, 15, 15);
610 			break;
611 		case B_LARGE_ICON:
612 			bounds.Set(0, 0, 31, 31);
613 			break;
614 		default:
615 			error = B_BAD_VALUE;
616 			break;
617 	}
618 
619 	// check parameters and initialization
620 	if (error == B_OK
621 		&& (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
622 		error = B_BAD_VALUE;
623 	}
624 	if (error == B_OK && InitCheck() != B_OK)
625 		error = B_NO_INIT;
626 
627 	bool success = false;
628 
629 	// get node MIME type, and, if that fails, the generic icon
630 	char mimeString[B_MIME_TYPE_LENGTH];
631 	if (error == B_OK) {
632 		if (GetType(mimeString) != B_OK) {
633 			struct stat stat;
634 			error = fNode->GetStat(&stat);
635 			if (error == B_OK) {
636 				// no type available -- get the icon for the appropriate type (file/dir/etc.)
637 				BMimeType type;
638 				if (S_ISREG(stat.st_mode)) {
639 					// is it an application (executable) or just a regular file?
640 					if ((stat.st_mode & S_IXUSR) != 0)
641 						type.SetTo(B_APP_MIME_TYPE);
642 					else
643 						type.SetTo(B_FILE_MIME_TYPE);
644 				} else if (S_ISDIR(stat.st_mode)) {
645 					// it's either a volume or just a standard directory
646 					fs_info info;
647 // 					if (fs_stat_dev(stat.st_dev, &info) == 0 && stat.st_ino == info.root)
648 // 						type.SetTo(B_VOLUME_MIME_TYPE);
649 // 					else
650 						type.SetTo(B_DIRECTORY_MIME_TYPE);
651 				} else if (S_ISLNK(stat.st_mode))
652 					type.SetTo(B_SYMLINK_MIME_TYPE);
653 
654 //				error = type.GetIcon(icon, iconSize);
655 error = B_ENTRY_NOT_FOUND;
656 				success = (error == B_OK);
657 			}
658 		}
659 	}
660 
661 	// Ask GetIcon().
662 	if (error == B_OK && !success)
663 		success = (GetIcon(icon, iconSize) == B_OK);
664 
665 	// Get the preferred application and ask the MIME database, if that
666 	// application has a special icon for the node's file type.
667 	if (error == B_OK && !success) {
668 		char signature[B_MIME_TYPE_LENGTH];
669 		if (GetPreferredApp(signature) == B_OK) {
670 //			BMimeType type(signature);
671 //			success = (type.GetIconForType(mimeString, icon, iconSize) == B_OK);
672 success = false;
673 		}
674 	}
675 
676 	// Ask the MIME database whether there is an icon for the node's file type.
677 	BMimeType nodeType;
678 	if (error == B_OK && !success) {
679  		nodeType.SetTo(mimeString);
680 // 		success = (nodeType.GetIcon(icon, iconSize) == B_OK);
681 	}
682 
683 	// Ask the MIME database for the preferred application for the node's
684 	// file type and whether this application has a special icon for the type.
685 	if (error == B_OK && !success) {
686 // 		char signature[B_MIME_TYPE_LENGTH];
687 // 		if (nodeType.GetPreferredApp(signature) == B_OK) {
688 // 			BMimeType type(signature);
689 // 			success = (type.GetIconForType(mimeString, icon, iconSize) == B_OK);
690 // 		}
691 	}
692 
693 	// Return the icon for "application/octet-stream" from the MIME database.
694 	if (error == B_OK && !success) {
695 // 		// get the "application/octet-stream" icon
696 // 		BMimeType type(B_FILE_MIME_TYPE);
697 // 		error = type.GetIcon(icon, iconSize);
698 error = B_ENTRY_NOT_FOUND;
699 		success = (error == B_OK);
700 	}
701 	return error;
702 }
703 
704 // GetTrackerIcon
705 /*!	\brief Gets the icon which tracker displays for the node referred to by
706 		   the supplied entry_ref.
707 
708 	This methods works similar to the non-static version. The first argument
709 	\a ref identifies the node in question.
710 
711 	\param ref An entry_ref referring to the node for which the icon shall be
712 		   retrieved.
713 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
714 		   to store the requested icon (16x16 for the mini and 32x32 for the
715 		   large icon).
716 	\param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON
717 		   for the mini and \c B_LARGE_ICON for the large icon.
718 	\return
719 	- \c B_OK: Everything went fine.
720 	- \c B_NO_INIT: The object is not properly initialized.
721 	- \c B_BAD_VALUE: \c NULL ref or \a icon, unsupported icon size \a iconSize or
722 		 bitmap dimensions (\a icon) and icon size (\a iconSize) do not match.
723 	- other error codes
724 */
725 status_t
726 BNodeInfo::GetTrackerIcon(const entry_ref *ref, BBitmap *icon, icon_size iconSize)
727 {
728 	// check ref param
729 	status_t error = (ref ? B_OK : B_BAD_VALUE);
730 	// init a BNode
731 	BNode node;
732 	if (error == B_OK)
733 		error = node.SetTo(ref);
734 	// init a BNodeInfo
735 	BNodeInfo nodeInfo;
736 	if (error == B_OK)
737 		error = nodeInfo.SetTo(&node);
738 	// let the non-static GetTrackerIcon() do the dirty work
739 	if (error == B_OK)
740 		error = nodeInfo.GetTrackerIcon(icon, iconSize);
741 	return error;
742 }
743 
744 void
745 BNodeInfo::_ReservedNodeInfo1()
746 {
747 }
748 
749 void
750 BNodeInfo::_ReservedNodeInfo2()
751 {
752 }
753 
754 void
755 BNodeInfo::_ReservedNodeInfo3()
756 {
757 }
758 
759 // =
760 /*!	\brief Privatized assignment operator to prevent usage.
761 */
762 BNodeInfo &
763 BNodeInfo::operator=(const BNodeInfo &nodeInfo)
764 {
765 	return *this;
766 }
767 
768 // copy constructor
769 /*!	\brief Privatized copy constructor to prevent usage.
770 */
771 BNodeInfo::BNodeInfo(const BNodeInfo &)
772 {
773 }
774 
775 
776 //	#pragma mark -
777 
778 namespace BPrivate {
779 
780 extern bool
781 CheckNodeIconHintPrivate(const BNode *node, bool whatever)
782 {
783 	// I've no idea what this is supposed to do exactly, but
784 	// it seems to tell Tracker if there is an icon for the
785 	// node. See kits/tracker/Model.cpp for details
786 	return true;
787 }
788 
789 }	// namespace BPrivate
790