xref: /haiku/src/kits/storage/NodeInfo.cpp (revision 32832cbe47f991cc6d2b29824903181d8baaaa63)
1 /*
2  * Copyright 2002-2010 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ingo Weinhold, bonefish@users.sf.net
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 #include <NodeInfo.h>
12 
13 #include <new>
14 #include <string.h>
15 
16 #include <MimeTypes.h>
17 #include <Bitmap.h>
18 #include <Entry.h>
19 #include <IconUtils.h>
20 #include <Node.h>
21 #include <Path.h>
22 #include <Rect.h>
23 
24 #include <fs_attr.h>
25 #include <fs_info.h>
26 
27 
28 using namespace std;
29 
30 
31 // attribute names
32 #define NI_BEOS "BEOS"
33 static const char* kNITypeAttribute			= NI_BEOS ":TYPE";
34 static const char* kNIPreferredAppAttribute	= NI_BEOS ":PREF_APP";
35 static const char* kNIAppHintAttribute		= NI_BEOS ":PPATH";
36 static const char* kNIMiniIconAttribute		= NI_BEOS ":M:STD_ICON";
37 static const char* kNILargeIconAttribute	= NI_BEOS ":L:STD_ICON";
38 static const char* kNIIconAttribute			= NI_BEOS ":ICON";
39 
40 
41 //	#pragma mark - BNodeInfo
42 
43 
44 BNodeInfo::BNodeInfo()
45 	:
46 	fNode(NULL),
47 	fCStatus(B_NO_INIT)
48 {
49 }
50 
51 
52 BNodeInfo::BNodeInfo(BNode* node)
53 	:
54 	fNode(NULL),
55 	fCStatus(B_NO_INIT)
56 {
57 	fCStatus = SetTo(node);
58 }
59 
60 
61 BNodeInfo::~BNodeInfo()
62 {
63 }
64 
65 
66 // Initializes the BNodeInfo to the supplied node.
67 status_t
68 BNodeInfo::SetTo(BNode* node)
69 {
70 	fNode = NULL;
71 	// check parameter
72 	fCStatus = (node && node->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
73 	if (fCStatus == B_OK)
74 		fNode = node;
75 
76 	return fCStatus;
77 }
78 
79 
80 // Returns whether the object has been properly initialized.
81 status_t
82 BNodeInfo::InitCheck() const
83 {
84 	return fCStatus;
85 }
86 
87 
88 // Writes the MIME type of the node into type.
89 status_t
90 BNodeInfo::GetType(char* type) const
91 {
92 	// check parameter and initialization
93 	status_t result = (type ? B_OK : B_BAD_VALUE);
94 	if (result == B_OK && InitCheck() != B_OK)
95 		result = B_NO_INIT;
96 	// get the attribute info and check type and length of the attr contents
97 	attr_info attrInfo;
98 	if (result == B_OK)
99 		result = fNode->GetAttrInfo(kNITypeAttribute, &attrInfo);
100 	if (result == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
101 		result = B_BAD_TYPE;
102 	if (result == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH)
103 		result = B_BAD_DATA;
104 
105 	// read the data
106 	if (result == B_OK) {
107 		ssize_t read = fNode->ReadAttr(kNITypeAttribute, attrInfo.type, 0,
108 									   type, attrInfo.size);
109 		if (read < 0)
110 			result = read;
111 		else if (read != attrInfo.size)
112 			result = B_ERROR;
113 
114 		if (result == B_OK) {
115 			// attribute strings doesn't have to be null terminated
116 			type[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0';
117 		}
118 	}
119 
120 	return result;
121 }
122 
123 // Sets the MIME type of the node. If type is NULL the BEOS:TYPE attribute is
124 // removed instead.
125 status_t
126 BNodeInfo::SetType(const char* type)
127 {
128 	// check parameter and initialization
129 	status_t result = B_OK;
130 	if (result == B_OK && type && strlen(type) >= B_MIME_TYPE_LENGTH)
131 		result = B_BAD_VALUE;
132 	if (result == B_OK && InitCheck() != B_OK)
133 		result = B_NO_INIT;
134 
135 	// write/remove the attribute
136 	if (result == B_OK) {
137 		if (type) {
138 			size_t toWrite = strlen(type) + 1;
139 			ssize_t written = fNode->WriteAttr(kNITypeAttribute,
140 											   B_MIME_STRING_TYPE, 0, type,
141 											   toWrite);
142 			if (written < 0)
143 				result = written;
144 			else if (written != (ssize_t)toWrite)
145 				result = B_ERROR;
146 		} else
147 			result = fNode->RemoveAttr(kNITypeAttribute);
148 	}
149 	return result;
150 }
151 
152 
153 // Gets the icon of the node.
154 status_t
155 BNodeInfo::GetIcon(BBitmap* icon, icon_size which) const
156 {
157 	const char* iconAttribute = kNIIconAttribute;
158 	const char* miniIconAttribute = kNIMiniIconAttribute;
159 	const char* largeIconAttribute = kNILargeIconAttribute;
160 
161 	return BIconUtils::GetIcon(fNode, iconAttribute, miniIconAttribute,
162 		largeIconAttribute, which, icon);
163 #if 0
164 	status_t result = B_OK;
165 	// set some icon size related variables
166 	const char* attribute = NULL;
167 	BRect bounds;
168 	uint32 attrType = 0;
169 	size_t attrSize = 0;
170 	switch (k) {
171 		case B_MINI_ICON:
172 			attribute = kNIMiniIconAttribute;
173 			bounds.Set(0, 0, 15, 15);
174 			attrType = B_MINI_ICON_TYPE;
175 			attrSize = 16 * 16;
176 			break;
177 		case B_LARGE_ICON:
178 			attribute = kNILargeIconAttribute;
179 			bounds.Set(0, 0, 31, 31);
180 			attrType = B_LARGE_ICON_TYPE;
181 			attrSize = 32 * 32;
182 			break;
183 		default:
184 			result = B_BAD_VALUE;
185 			break;
186 	}
187 
188 	// check parameter and initialization
189 	if (result == B_OK
190 		&& (icon == NULL || icon->InitCheck() != B_OK
191 			|| icon->Bounds() != bounds)) {
192 		result = B_BAD_VALUE;
193 	}
194 	if (result == B_OK && InitCheck() != B_OK)
195 		result = B_NO_INIT;
196 
197 	// get the attribute info and check type and size of the attr contents
198 	attr_info attrInfo;
199 	if (result == B_OK)
200 		result = fNode->GetAttrInfo(attribute, &attrInfo);
201 
202 	if (result == B_OK && attrInfo.type != attrType)
203 		result = B_BAD_TYPE;
204 
205 	if (result == B_OK && attrInfo.size != attrSize)
206 		result = B_BAD_DATA;
207 
208 	// read the attribute
209 	if (result == B_OK) {
210 		bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
211 		char *buffer = NULL;
212 		ssize_t read;
213 		if (otherColorSpace) {
214 			// other color space than stored in attribute
215 			buffer = new(nothrow) char[attrSize];
216 			if (!buffer)
217 				result = B_NO_MEMORY;
218 			if (result == B_OK) {
219 				read = fNode->ReadAttr(attribute, attrType, 0, buffer,
220 					attrSize);
221 			}
222 		} else {
223 			read = fNode->ReadAttr(attribute, attrType, 0, icon->Bits(),
224 				attrSize);
225 		}
226 		if (result == B_OK) {
227 			if (read < 0)
228 				result = read;
229 			else if (read != attrInfo.size)
230 				result = B_ERROR;
231 		}
232 		if (otherColorSpace) {
233 			// other color space than stored in attribute
234 			if (result == B_OK) {
235 				result = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
236 					 0, B_CMAP8);
237 			}
238 			delete[] buffer;
239 		}
240 	}
241 
242 	return result;
243 #endif
244 }
245 
246 
247 // Sets the icon of the node. If icon is NULL, the attribute is removed
248 // instead.
249 status_t
250 BNodeInfo::SetIcon(const BBitmap* icon, icon_size which)
251 {
252 	status_t result = B_OK;
253 
254 	// set some icon size related variables
255 	const char* attribute = NULL;
256 	BRect bounds;
257 	uint32 attrType = 0;
258 	size_t attrSize = 0;
259 
260 	switch (which) {
261 		case B_MINI_ICON:
262 			attribute = kNIMiniIconAttribute;
263 			bounds.Set(0, 0, 15, 15);
264 			attrType = B_MINI_ICON_TYPE;
265 			attrSize = 16 * 16;
266 			break;
267 
268 		case B_LARGE_ICON:
269 			attribute = kNILargeIconAttribute;
270 			bounds.Set(0, 0, 31, 31);
271 			attrType = B_LARGE_ICON_TYPE;
272 			attrSize = 32 * 32;
273 			break;
274 
275 		default:
276 			result = B_BAD_VALUE;
277 			break;
278 	}
279 
280 	// check parameter and initialization
281 	if (result == B_OK && icon != NULL
282 		&& (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
283 		result = B_BAD_VALUE;
284 	}
285 	if (result == B_OK && InitCheck() != B_OK)
286 		result = B_NO_INIT;
287 
288 	// write/remove the attribute
289 	if (result == B_OK) {
290 		if (icon != NULL) {
291 			bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
292 			ssize_t written = 0;
293 			if (otherColorSpace) {
294 				BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8);
295 				result = bitmap.InitCheck();
296 				if (result == B_OK)
297 					result = bitmap.ImportBits(icon);
298 
299 				if (result == B_OK) {
300 					written = fNode->WriteAttr(attribute, attrType, 0,
301 						bitmap.Bits(), attrSize);
302 				}
303 			} else {
304 				written = fNode->WriteAttr(attribute, attrType, 0,
305 					icon->Bits(), attrSize);
306 			}
307 			if (result == B_OK) {
308 				if (written < 0)
309 					result = written;
310 				else if (written != (ssize_t)attrSize)
311 					result = B_ERROR;
312 			}
313 		} else {
314 			// no icon given => remove
315 			result = fNode->RemoveAttr(attribute);
316 		}
317 	}
318 
319 	return result;
320 }
321 
322 
323 // Gets the icon of the node.
324 status_t
325 BNodeInfo::GetIcon(uint8** data, size_t* size, type_code* type) const
326 {
327 	// check params
328 	if (data == NULL || size == NULL || type == NULL)
329 		return B_BAD_VALUE;
330 
331 	// check initialization
332 	if (InitCheck() != B_OK)
333 		return B_NO_INIT;
334 
335 	// get the attribute info and check type and size of the attr contents
336 	attr_info attrInfo;
337 	status_t ret = fNode->GetAttrInfo(kNIIconAttribute, &attrInfo);
338 	if (ret < B_OK)
339 		return ret;
340 
341 	// chicken out on unrealisticly large attributes
342 	if (attrInfo.size > 128 * 1024)
343 		return B_ERROR;
344 
345 	// fill the params
346 	*type = attrInfo.type;
347 	*size = attrInfo.size;
348 	*data = new (nothrow) uint8[*size];
349 
350 	if (!*data)
351 		return B_NO_MEMORY;
352 
353 	// featch the data
354 	ssize_t read = fNode->ReadAttr(kNIIconAttribute, *type, 0, *data, *size);
355 	if (read != attrInfo.size) {
356 		delete[] *data;
357 		*data = NULL;
358 		return B_ERROR;
359 	}
360 
361 	return B_OK;
362 }
363 
364 
365 // Sets the node icon of the node. If data is NULL of size is 0, the
366 // "BEOS:ICON" attribute is removed instead.
367 status_t
368 BNodeInfo::SetIcon(const uint8* data, size_t size)
369 {
370 	// check initialization
371 	if (InitCheck() != B_OK)
372 		return B_NO_INIT;
373 
374 	status_t result = B_OK;
375 
376 	// write/remove the attribute
377 	if (data && size > 0) {
378 		ssize_t written = fNode->WriteAttr(kNIIconAttribute,
379 			B_VECTOR_ICON_TYPE, 0, data, size);
380 		if (written < 0)
381 			result = (status_t)written;
382 		else if (written != (ssize_t)size)
383 			result = B_ERROR;
384 	} else {
385 		// no icon given => remove
386 		result = fNode->RemoveAttr(kNIIconAttribute);
387 	}
388 
389 	return result;
390 }
391 
392 
393 // Gets the preferred application of the node.
394 status_t
395 BNodeInfo::GetPreferredApp(char* signature, app_verb verb) const
396 {
397 	// check parameter and initialization
398 	status_t result = (signature && verb == B_OPEN ? B_OK : B_BAD_VALUE);
399 	if (result == B_OK && InitCheck() != B_OK)
400 		result = B_NO_INIT;
401 
402 	// get the attribute info and check type and length of the attr contents
403 	attr_info attrInfo;
404 	if (result == B_OK)
405 		result = fNode->GetAttrInfo(kNIPreferredAppAttribute, &attrInfo);
406 
407 	if (result == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
408 		result = B_BAD_TYPE;
409 
410 	if (result == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH)
411 		result = B_BAD_DATA;
412 
413 	// read the data
414 	if (result == B_OK) {
415 		ssize_t read = fNode->ReadAttr(kNIPreferredAppAttribute, attrInfo.type,
416 			0, signature, attrInfo.size);
417 		if (read < 0)
418 			result = read;
419 		else if (read != attrInfo.size)
420 			result = B_ERROR;
421 
422 		if (result == B_OK) {
423 			// attribute strings doesn't have to be null terminated
424 			signature[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0';
425 		}
426 	}
427 
428 	return result;
429 }
430 
431 
432 // Sets the preferred application of the node. If signature is NULL, the
433 // "BEOS:PREF_APP" attribute is removed instead.
434 status_t
435 BNodeInfo::SetPreferredApp(const char* signature, app_verb verb)
436 {
437 	// check parameters and initialization
438 	status_t result = (verb == B_OPEN ? B_OK : B_BAD_VALUE);
439 	if (result == B_OK && signature && strlen(signature) >= B_MIME_TYPE_LENGTH)
440 		result = B_BAD_VALUE;
441 
442 	if (result == B_OK && InitCheck() != B_OK)
443 		result = B_NO_INIT;
444 
445 	// write/remove the attribute
446 	if (result == B_OK) {
447 		if (signature) {
448 			size_t toWrite = strlen(signature) + 1;
449 			ssize_t written = fNode->WriteAttr(kNIPreferredAppAttribute,
450 				B_MIME_STRING_TYPE, 0, signature, toWrite);
451 			if (written < 0)
452 				result = written;
453 			else if (written != (ssize_t)toWrite)
454 				result = B_ERROR;
455 		} else
456 			result = fNode->RemoveAttr(kNIPreferredAppAttribute);
457 	}
458 
459 	return result;
460 }
461 
462 
463 // Fills out ref with a pointer to a hint about what application will open
464 // this node.
465 status_t
466 BNodeInfo::GetAppHint(entry_ref* ref) const
467 {
468 	// check parameter and initialization
469 	status_t result = (ref ? B_OK : B_BAD_VALUE);
470 	if (result == B_OK && InitCheck() != B_OK)
471 		result = B_NO_INIT;
472 
473 	// get the attribute info and check type and length of the attr contents
474 	attr_info attrInfo;
475 	if (result == B_OK)
476 		result = fNode->GetAttrInfo(kNIAppHintAttribute, &attrInfo);
477 
478 	// NOTE: The attribute type should be B_STRING_TYPE, but R5 uses
479 	// B_MIME_STRING_TYPE.
480 	if (result == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
481 		result = B_BAD_TYPE;
482 
483 	if (result == B_OK && attrInfo.size > B_PATH_NAME_LENGTH)
484 		result = B_BAD_DATA;
485 
486 	// read the data
487 	if (result == B_OK) {
488 		char path[B_PATH_NAME_LENGTH];
489 		ssize_t read = fNode->ReadAttr(kNIAppHintAttribute, attrInfo.type, 0,
490 			path, attrInfo.size);
491 		if (read < 0)
492 			result = read;
493 		else if (read != attrInfo.size)
494 			result = B_ERROR;
495 
496 		// get the entry_ref for the path
497 		if (result == B_OK) {
498 			// attribute strings doesn't have to be null terminated
499 			path[min_c(attrInfo.size, B_PATH_NAME_LENGTH - 1)] = '\0';
500 			result = get_ref_for_path(path, ref);
501 		}
502 	}
503 
504 	return result;
505 }
506 
507 
508 // Sets the app hint of the node. If ref is NULL, the "BEOS:PPATH" attribute
509 // is removed instead.
510 status_t
511 BNodeInfo::SetAppHint(const entry_ref* ref)
512 {
513 	// check parameter and initialization
514 	if (InitCheck() != B_OK)
515 		return B_NO_INIT;
516 
517 	status_t result = B_OK;
518 	if (ref != NULL) {
519 		// write/remove the attribute
520 		BPath path;
521 		result = path.SetTo(ref);
522 		if (result == B_OK) {
523 			size_t toWrite = strlen(path.Path()) + 1;
524 			ssize_t written = fNode->WriteAttr(kNIAppHintAttribute,
525 				B_MIME_STRING_TYPE, 0, path.Path(), toWrite);
526 			if (written < 0)
527 				result = written;
528 			else if (written != (ssize_t)toWrite)
529 				result = B_ERROR;
530 		}
531 	} else
532 		result = fNode->RemoveAttr(kNIAppHintAttribute);
533 
534 	return result;
535 }
536 
537 
538 // Gets the icon displayed by Tracker for the icon.
539 status_t
540 BNodeInfo::GetTrackerIcon(BBitmap* icon, icon_size which) const
541 {
542 	if (icon == NULL)
543 		return B_BAD_VALUE;
544 
545 	// set some icon size related variables
546 	BRect bounds;
547 	switch (which) {
548 		case B_MINI_ICON:
549 			bounds.Set(0, 0, 15, 15);
550 			break;
551 
552 		case B_LARGE_ICON:
553 			bounds.Set(0, 0, 31, 31);
554 			break;
555 
556 		default:
557 //			result = B_BAD_VALUE;
558 			// NOTE: added to be less strict and support scaled icons
559 			bounds = icon->Bounds();
560 			break;
561 	}
562 
563 	// check parameters and initialization
564 	if (icon->InitCheck() != B_OK || icon->Bounds() != bounds)
565 		return B_BAD_VALUE;
566 
567 	if (InitCheck() != B_OK)
568 		return B_NO_INIT;
569 
570 	// Ask GetIcon() first.
571 	if (GetIcon(icon, which) == B_OK)
572 		return B_OK;
573 
574 	// If not successful, see if the node has a type available at all.
575 	// If no type is available, use one of the standard types.
576 	status_t result = B_OK;
577 	char mimeString[B_MIME_TYPE_LENGTH];
578 	if (GetType(mimeString) != B_OK) {
579 		// Get the icon from a mime type...
580 		BMimeType type;
581 
582 		struct stat stat;
583 		result = fNode->GetStat(&stat);
584 		if (result == B_OK) {
585 			// no type available -- get the icon for the appropriate type
586 			// (file/dir/etc.)
587 			if (S_ISREG(stat.st_mode)) {
588 				// is it an application (executable) or just a regular file?
589 				if ((stat.st_mode & S_IXUSR) != 0)
590 					type.SetTo(B_APP_MIME_TYPE);
591 				else
592 					type.SetTo(B_FILE_MIME_TYPE);
593 			} else if (S_ISDIR(stat.st_mode)) {
594 				// it's either a volume or just a standard directory
595 				fs_info info;
596 				if (fs_stat_dev(stat.st_dev, &info) == 0
597 					&& stat.st_ino == info.root) {
598 					type.SetTo(B_VOLUME_MIME_TYPE);
599 				} else
600 					type.SetTo(B_DIRECTORY_MIME_TYPE);
601 			} else if (S_ISLNK(stat.st_mode))
602 				type.SetTo(B_SYMLINK_MIME_TYPE);
603 		} else {
604 			// GetStat() failed. Return the icon for
605 			// "application/octet-stream" from the MIME database.
606 			type.SetTo(B_FILE_MIME_TYPE);
607 		}
608 
609 		return type.GetIcon(icon, which);
610 	} else {
611 		// We know the mimetype of the node.
612 		bool success = false;
613 
614 		// Get the preferred application and ask the MIME database, if that
615 		// application has a special icon for the node's file type.
616 		char signature[B_MIME_TYPE_LENGTH];
617 		if (GetPreferredApp(signature) == B_OK) {
618 			BMimeType type(signature);
619 			success = type.GetIconForType(mimeString, icon, which) == B_OK;
620 		}
621 
622 		// ToDo: Confirm Tracker asks preferred app icons before asking
623 		// mime icons.
624 
625 		BMimeType nodeType(mimeString);
626 
627 		// Ask the MIME database for the preferred application for the node's
628 		// file type and whether this application has a special icon for the
629 		// type.
630 		if (!success && nodeType.GetPreferredApp(signature) == B_OK) {
631 			BMimeType type(signature);
632 			success = type.GetIconForType(mimeString, icon, which) == B_OK;
633 		}
634 
635 		// Ask the MIME database whether there is an icon for the node's file
636 		// type.
637 		if (!success)
638 			success = nodeType.GetIcon(icon, which) == B_OK;
639 
640 		// Get the super type if still no success.
641 		BMimeType superType;
642 		if (!success && nodeType.GetSupertype(&superType) == B_OK) {
643 			// Ask the MIME database for the preferred application for the
644 			// node's super type and whether this application has a special
645 			// icon for the type.
646 			if (superType.GetPreferredApp(signature) == B_OK) {
647 				BMimeType type(signature);
648 				success = type.GetIconForType(superType.Type(), icon,
649 					which) == B_OK;
650 			}
651 			// Get the icon of the super type itself.
652 			if (!success)
653 				success = superType.GetIcon(icon, which) == B_OK;
654 		}
655 
656 		if (success)
657 			return B_OK;
658 	}
659 
660 	return B_ERROR;
661 }
662 
663 
664 // Gets the icon displayed by Tracker for the node referred to by ref.
665 status_t
666 BNodeInfo::GetTrackerIcon(const entry_ref* ref, BBitmap* icon, icon_size which)
667 {
668 	// check ref param
669 	status_t result = (ref ? B_OK : B_BAD_VALUE);
670 
671 	// init a BNode
672 	BNode node;
673 	if (result == B_OK)
674 		result = node.SetTo(ref);
675 
676 	// init a BNodeInfo
677 	BNodeInfo nodeInfo;
678 	if (result == B_OK)
679 		result = nodeInfo.SetTo(&node);
680 
681 	// let the non-static GetTrackerIcon() do the dirty work
682 	if (result == B_OK)
683 		result = nodeInfo.GetTrackerIcon(icon, which);
684 
685 	return result;
686 }
687 
688 
689 // NOTE: The following method is provided for binary compatibility purposes
690 // (for example the program "Guido" depends on this.)
691 extern "C"
692 status_t
693 GetTrackerIcon__9BNodeInfoP9entry_refP7BBitmap9icon_size(
694 	BNodeInfo* nodeInfo, entry_ref* ref,
695 	BBitmap* bitmap, icon_size iconSize)
696 {
697 	// NOTE: nodeInfo is ignored - maybe that's wrong!
698 	return BNodeInfo::GetTrackerIcon(ref, bitmap, iconSize);
699 }
700 
701 
702 void BNodeInfo::_ReservedNodeInfo1() {}
703 void BNodeInfo::_ReservedNodeInfo2() {}
704 void BNodeInfo::_ReservedNodeInfo3() {}
705 
706 
707 // Assignment operator is declared private to prevent it from being created
708 // automatically by the compiler.
709 BNodeInfo&
710 BNodeInfo::operator=(const BNodeInfo &nodeInfo)
711 {
712 	return *this;
713 }
714 
715 
716 // Copy constructor is declared private to prevent it from being created
717 // automatically by the compiler.
718 BNodeInfo::BNodeInfo(const BNodeInfo &)
719 {
720 }
721 
722 
723 namespace BPrivate {
724 
725 // Private method used by Tracker. This should be moved to the Tracker
726 // source.
727 extern bool
728 CheckNodeIconHintPrivate(const BNode* node, bool checkMiniIconOnly)
729 {
730 	attr_info info;
731 	if (node->GetAttrInfo(kNIMiniIconAttribute, &info) != B_OK && checkMiniIconOnly)
732 		return false;
733 
734 	if (node->GetAttrInfo(kNILargeIconAttribute, &info) != B_OK)
735 		return false;
736 
737 	return true;
738 }
739 
740 }	// namespace BPrivate
741