xref: /haiku/src/kits/storage/Mime.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
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 Mime.cpp
12 	Mime type C functions implementation.
13 */
14 
15 #include <fs_attr.h>
16 #include <fs_info.h>
17 #include <Bitmap.h>
18 #include <Drivers.h>
19 #include <Entry.h>
20 #include <Mime.h>
21 #include <MimeType.h>
22 #include <mime/database_access.h>
23 #include <Node.h>
24 #include <RegistrarDefs.h>
25 #include <Roster.h>
26 #include <RosterPrivate.h>
27 
28 #include <unistd.h>
29 #include <sys/ioctl.h>
30 
31 using namespace BPrivate;
32 
33 enum {
34 	NOT_IMPLEMENTED	= B_ERROR,
35 };
36 
37 // do_mime_update
38 //! Helper function that contacts the registrar for mime update calls
39 status_t
40 do_mime_update(int32 what, const char *path, int recursive,
41 	int synchronous, int force)
42 {
43 	BEntry root;
44 	entry_ref ref;
45 
46 	status_t err = root.SetTo(path ? path : "/");
47 	if (!err)
48 		err = root.GetRef(&ref);
49 	if (!err) {
50 		BMessage msg(what);
51 		BMessage reply;
52 		status_t result;
53 
54 		// Build and send the message, read the reply
55 		if (!err)
56 			err = msg.AddRef("entry", &ref);
57 		if (!err)
58 			err = msg.AddBool("recursive", recursive);
59 		if (!err)
60 			err = msg.AddBool("synchronous", synchronous);
61 		if (!err)
62 			err = msg.AddInt32("force", force);
63 		if (!err)
64 			err = BRoster::Private().SendTo(&msg, &reply, true);
65 		if (!err)
66 			err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE;
67 		if (!err)
68 			err = reply.FindInt32("result", &result);
69 		if (!err)
70 			err = result;
71 	}
72 	return err;
73 }
74 
75 // update_mime_info
76 /*!	\brief Updates the MIME information (i.e MIME type) for one or more files.
77 	If \a path points to a file, the MIME information for this file are
78 	updated only. If it points to a directory and \a recursive is non-null,
79 	the information for all the files in the given directory tree are updated.
80 	If path is \c NULL all files are considered; \a recursive is ignored in
81 	this case.
82 	\param path The path to a file or directory, or \c NULL.
83 	\param recursive Non-null to trigger recursive behavior.
84 	\param synchronous If non-null update_mime_info() waits until the
85 		   operation is finished, otherwise it returns immediately and the
86 		   update is done asynchronously.
87 	\param force Specifies how to handle files that already have MIME
88 		   information:
89 			- \c B_UPDATE_MIME_INFO_NO_FORCE: Files that already have a
90 			  \c BEOS:TYPE attribute won't be updated.
91 			- \c B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE: Files that already have a
92 			  \c BEOS:TYPE attribute will be updated too, but \c BEOS:TYPE
93 			  itself will remain untouched.
94 			- \c B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL: Similar to
95 			  \c B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE, but the \c BEOS:TYPE
96 			  attribute will be updated too.
97 	\return
98 	- \c B_OK: Everything went fine.
99 	- An error code otherwise.
100 */
101 int
102 update_mime_info(const char *path, int recursive, int synchronous, int force)
103 {
104 	// Force recursion when given a NULL path
105 	if (!path)
106 		recursive = true;
107 
108 	return do_mime_update(B_REG_MIME_UPDATE_MIME_INFO, path, recursive,
109 		synchronous, force);
110 }
111 
112 // create_app_meta_mime
113 /*!	Creates a MIME database entry for one or more applications.
114 	\a path should either point to an application file or should be \c NULL.
115 	In the first case a MIME database entry for that application is created,
116 	in the second case entries for all applications are created.
117 	\param path The path to an application file, or \c NULL.
118 	\param recursive Currently unused.
119 	\param synchronous If non-null create_app_meta_mime() waits until the
120 		   operation is finished, otherwise it returns immediately and the
121 		   operation is done asynchronously.
122 	\param force If non-null, entries are created even if they do already
123 		   exist.
124 	\return
125 	- \c B_OK: Everything went fine.
126 	- An error code otherwise.
127 */
128 status_t
129 create_app_meta_mime(const char *path, int recursive, int synchronous,
130 	int force)
131 {
132 	// If path is NULL, we are recursive, otherwise no.
133 	recursive = !path;
134 
135 	return do_mime_update(B_REG_MIME_CREATE_APP_META_MIME, path, recursive,
136 		synchronous, force);
137 }
138 
139 // get_device_icon
140 /*!	Retrieves an icon associated with a given device.
141 	\param dev The path to the device.
142 	\param icon A pointer to a buffer the icon data shall be written to.
143 	\param size The size of the icon. Currently the sizes 16 (small, i.e
144 	            \c B_MINI_ICON) and 32 (large, 	i.e. \c B_LARGE_ICON) are
145 	            supported.
146 
147 	\todo The mounted directories for volumes can also have META:X:STD_ICON
148 		  attributes. Should those attributes override the icon returned
149 		  by ioctl(,B_GET_ICON,)?
150 
151 	\return
152 	- \c B_OK: Everything went fine.
153 	- An error code otherwise.
154 */
155 status_t
156 get_device_icon(const char *dev, void *icon, int32 size)
157 {
158 	status_t err = dev && icon && (size == B_LARGE_ICON || size == B_MINI_ICON)
159 		? B_OK : B_BAD_VALUE;
160 
161 	int fd = -1;
162 
163 	if (!err) {
164 		fd = open(dev, O_RDONLY);
165 		err = fd != -1 ? B_OK : B_BAD_VALUE;
166 	}
167 	if (!err) {
168 		device_icon iconData = { size, icon };
169 		err = ioctl(fd, B_GET_ICON, &iconData);
170 	}
171 	if (fd != -1) {
172 		// If the file descriptor was open()ed, we need to close it
173 		// regardless. Only if we haven't yet encountered any errors
174 		// do we make note close()'s return value, however.
175 		status_t error = close(fd);
176 		if (!err)
177 			err = error;
178 	}
179 	return err;
180 }
181 
182 // get_device_icon
183 /*!	Retrieves an icon associated with a given device.
184 	\param dev The path to the device.
185 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
186 		   to store the requested icon (16x16 for the mini and 32x32 for the
187 		   large icon).
188 	\param which Specifies the size of the icon to be retrieved:
189 		   \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon.
190 
191 	\todo The mounted directories for volumes can also have META:X:STD_ICON
192 		  attributes. Should those attributes override the icon returned
193 		  by ioctl(,B_GET_ICON,)?
194 
195 	\return
196 	- \c B_OK: Everything went fine.
197 	- An error code otherwise.
198 */
199 status_t
200 get_device_icon(const char *dev, BBitmap *icon, icon_size which)
201 {
202 	// check parameters
203 	status_t error = (dev && icon ? B_OK : B_BAD_VALUE);
204 	BRect rect;
205 	if (error == B_OK) {
206 		if (which == B_MINI_ICON)
207 			rect.Set(0, 0, 15, 15);
208 		else if (which == B_LARGE_ICON)
209 			rect.Set(0, 0, 31, 31);
210 		else
211 			error = B_BAD_VALUE;
212 	}
213 	// check whether icon size and bitmap dimensions do match
214 	if (error == B_OK
215 		&& (icon->Bounds() != rect || icon->ColorSpace() != B_CMAP8)) {
216 		error = B_BAD_VALUE;
217 	}
218 	// TODO: support bitmap with other color spaces!
219 	// get the icon
220 	if (error == B_OK)
221 		error = get_device_icon(dev, icon->Bits(), which);
222 	return error;
223 }
224 
225