xref: /haiku/src/kits/storage/Mime.cpp (revision 5412911f7f8ca41340b0f5cb928ed9726322ab44)
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.AddBool("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 If non-null, also the information for files are updated that
82 		   have already been updated.
83 	\return
84 	- \c B_OK: Everything went fine.
85 	- An error code otherwise.
86 */
87 int
88 update_mime_info(const char *path, int recursive, int synchronous, int force)
89 {
90 	// Force recursion when given a NULL path
91 	if (!path)
92 		recursive = true;
93 
94 	return do_mime_update(B_REG_MIME_UPDATE_MIME_INFO, path, recursive,
95 		synchronous, force);
96 }
97 
98 // create_app_meta_mime
99 /*!	Creates a MIME database entry for one or more applications.
100 	\a path should either point to an application file or should be \c NULL.
101 	In the first case a MIME database entry for that application is created,
102 	in the second case entries for all applications are created.
103 	\param path The path to an application file, or \c NULL.
104 	\param recursive Currently unused.
105 	\param synchronous If non-null create_app_meta_mime() waits until the
106 		   operation is finished, otherwise it returns immediately and the
107 		   operation is done asynchronously.
108 	\param force If non-null, entries are created even if they do already
109 		   exist.
110 	\return
111 	- \c B_OK: Everything went fine.
112 	- An error code otherwise.
113 */
114 status_t
115 create_app_meta_mime(const char *path, int recursive, int synchronous,
116 					 int force)
117 {
118 	// If path is NULL, we are recursive, otherwise no.
119 	recursive = !path;
120 
121 	return do_mime_update(B_REG_MIME_CREATE_APP_META_MIME, path, recursive,
122 		synchronous, force);
123 }
124 
125 // get_device_icon
126 /*!	Retrieves an icon associated with a given device.
127 	\param dev The path to the device.
128 	\param icon A pointer to a buffer the icon data shall be written to.
129 	\param size The size of the icon. Currently the sizes 16 (small, i.e
130 	            \c B_MINI_ICON) and 32 (large, 	i.e. \c B_LARGE_ICON) are
131 	            supported.
132 
133 	\todo The mounted directories for volumes can also have META:X:STD_ICON
134 		  attributes. Should those attributes override the icon returned
135 		  by ioctl(,B_GET_ICON,)?
136 
137 	\return
138 	- \c B_OK: Everything went fine.
139 	- An error code otherwise.
140 */
141 status_t
142 get_device_icon(const char *dev, void *icon, int32 size)
143 {
144 	status_t err = dev && icon
145 				     && (size == B_LARGE_ICON || size == B_MINI_ICON)
146 				       ? B_OK : B_BAD_VALUE;
147 
148 	int fd = -1;
149 
150 	if (!err) {
151 		fd = open(dev, O_RDONLY);
152 		err = fd != -1 ? B_OK : B_BAD_VALUE;
153 	}
154 	if (!err) {
155 		device_icon iconData = { size, icon };
156 		err = ioctl(fd, B_GET_ICON, &iconData);
157 	}
158 	if (fd != -1) {
159 		// If the file descriptor was open()ed, we need to close it
160 		// regardless. Only if we haven't yet encountered any errors
161 		// do we make note close()'s return value, however.
162 		status_t error = close(fd);
163 		if (!err)
164 			err = error;
165 	}
166 	return err;
167 }
168 
169 // get_device_icon
170 /*!	Retrieves an icon associated with a given device.
171 	\param dev The path to the device.
172 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
173 		   to store the requested icon (16x16 for the mini and 32x32 for the
174 		   large icon).
175 	\param which Specifies the size of the icon to be retrieved:
176 		   \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon.
177 
178 	\todo The mounted directories for volumes can also have META:X:STD_ICON
179 		  attributes. Should those attributes override the icon returned
180 		  by ioctl(,B_GET_ICON,)?
181 
182 	\return
183 	- \c B_OK: Everything went fine.
184 	- An error code otherwise.
185 */
186 status_t
187 get_device_icon(const char *dev, BBitmap *icon, icon_size which)
188 {
189 	// check parameters
190 	status_t error = (dev && icon ? B_OK : B_BAD_VALUE);
191 	BRect rect;
192 	if (error == B_OK) {
193 		if (which == B_MINI_ICON)
194 			rect.Set(0, 0, 15, 15);
195 		else if (which == B_LARGE_ICON)
196 			rect.Set(0, 0, 31, 31);
197 		else
198 			error = B_BAD_VALUE;
199 	}
200 	// check whether icon size and bitmap dimensions do match
201 	if (error == B_OK
202 		&& (icon->Bounds() != rect || icon->ColorSpace() != B_CMAP8)) {
203 		error = B_BAD_VALUE;
204 	}
205 	// get the icon
206 	if (error == B_OK)
207 		error = get_device_icon(dev, icon->Bits(), which);
208 	return error;
209 }
210 
211