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