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