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