xref: /onnv-gate/usr/src/lib/libparted/common/libparted/device.c (revision 9663:ace9a2ac3683)
1 /*
2     libparted - a library for manipulating disk partitions
3     Copyright (C) 1999 - 2001, 2005, 2007 Free Software Foundation, Inc.
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /** \file device.c */
20 
21 /**
22  * \addtogroup PedDevice
23  *
24  * \brief Device access.
25  *
26  * When ped_device_probe_all() is called, libparted attempts to detect all
27  * devices.  It constructs a list which can be accessed with
28  * ped_device_get_next().
29  *
30  * If you want to use a device that isn't on the list, use
31  * ped_device_get().  Also, there may be OS-specific constructors, for creating
32  * devices from file descriptors, stores, etc.  For example,
33  * ped_device_new_from_store().
34  *
35  * @{
36  */
37 
38 #include <config.h>
39 
40 #include <parted/parted.h>
41 #include <parted/debug.h>
42 
43 #include <limits.h>
44 #include <unistd.h>
45 #include <errno.h>
46 
47 static PedDevice*	devices; /* legal advice says: initialized to NULL,
48 				    under section 6.7.8 part 10
49 				    of ISO/EIC 9899:1999 */
50 
51 #ifndef HAVE_CANONICALIZE_FILE_NAME
52 char *
canonicalize_file_name(const char * name)53 canonicalize_file_name (const char *name)
54 {
55 	char *	buf;
56 	int	size;
57 	char *	result;
58 
59 #ifdef PATH_MAX
60 	size = PATH_MAX;
61 #else
62 	/* Bigger is better; realpath has no way todo bounds checking.  */
63 	size = 4096;
64 #endif
65 
66 	/* Just in case realpath does not NULL terminate the string
67 	 * or it just fits in SIZE without a NULL terminator.  */
68 	buf = calloc (size + 1, sizeof(char));
69 	if (! buf) {
70 		errno = ENOMEM;
71 		return NULL;
72 	}
73 
74 	result = realpath (name, buf);
75 	if (! result)
76 		free (buf);
77 
78 	return result;
79 }
80 #else
81 extern char *canonicalize_file_name (const char *name);
82 #endif /* !HAVE_CANONICALIZE_FILE_NAME */
83 
84 static void
_device_register(PedDevice * dev)85 _device_register (PedDevice* dev)
86 {
87 	PedDevice*	walk;
88 	for (walk = devices; walk && walk->next; walk = walk->next);
89 	if (walk)
90 		walk->next = dev;
91 	else
92 		devices = dev;
93 	dev->next = NULL;
94 }
95 
96 static void
_device_unregister(PedDevice * dev)97 _device_unregister (PedDevice* dev)
98 {
99 	PedDevice*	walk;
100 	PedDevice*	last = NULL;
101 
102 	for (walk = devices; walk != NULL; last = walk, walk = walk->next) {
103 		if (walk == dev) break;
104 	}
105 
106 	if (last)
107 		last->next = dev->next;
108 	else
109 		devices = dev->next;
110 }
111 
112 /**
113  * Returns the next device that was detected by ped_device_probe_all(), or
114  * calls to ped_device_get_next().
115  * If dev is NULL, returns the first device.
116  *
117  * \return NULL if dev is the last device.
118  */
119 PedDevice*
ped_device_get_next(const PedDevice * dev)120 ped_device_get_next (const PedDevice* dev)
121 {
122 	if (dev)
123 		return dev->next;
124 	else
125 		return devices;
126 }
127 
128 void
_ped_device_probe(const char * path)129 _ped_device_probe (const char* path)
130 {
131 	PedDevice*	dev;
132 
133 	PED_ASSERT (path != NULL, return);
134 
135 	ped_exception_fetch_all ();
136 	dev = ped_device_get (path);
137 	if (!dev)
138 		ped_exception_catch ();
139 	ped_exception_leave_all ();
140 }
141 
142 /**
143  * Attempts to detect all devices.
144  */
145 void
ped_device_probe_all()146 ped_device_probe_all ()
147 {
148 	ped_architecture->dev_ops->probe_all ();
149 }
150 
151 /**
152  * Close/free all devices.
153  * Called by ped_done(), so you do not need to worry about it.
154  */
155 void
ped_device_free_all()156 ped_device_free_all ()
157 {
158 	while (devices)
159 		ped_device_destroy (devices);
160 }
161 
162 /**
163  * Gets the device "name", where name is usually the block device, e.g.
164  * /dev/sdb.  If the device wasn't detected with ped_device_probe_all(),
165  * an attempt will be made to detect it again.  If it is found, it will
166  * be added to the list.
167  */
168 PedDevice*
ped_device_get(const char * path)169 ped_device_get (const char* path)
170 {
171 	PedDevice*	walk;
172 	char*		normal_path;
173 
174 	PED_ASSERT (path != NULL, return NULL);
175 	normal_path = canonicalize_file_name (path);
176 	if (!normal_path)
177 		/* Well, maybe it is just that the file does not exist.
178 		 * Try it anyway.  */
179 		normal_path = strdup (path);
180 	if (!normal_path)
181 		return NULL;
182 
183 	for (walk = devices; walk != NULL; walk = walk->next) {
184 		if (!strcmp (walk->path, normal_path)) {
185 			ped_free (normal_path);
186 			return walk;
187 		}
188 	}
189 
190 	walk = ped_architecture->dev_ops->_new (normal_path);
191 	ped_free (normal_path);
192 	if (!walk)
193 		return NULL;
194 
195 	_device_register (walk);
196 	return walk;
197 }
198 
199 /**
200  * Destroys a device and removes it from the device list, and frees
201  * all resources associated with the device (all resources allocated
202  * when the device was created).
203  */
204 void
ped_device_destroy(PedDevice * dev)205 ped_device_destroy (PedDevice* dev)
206 {
207 	_device_unregister (dev);
208 
209 	while (dev->open_count) {
210 		if (!ped_device_close (dev))
211 			break;
212 	}
213 
214 	ped_architecture->dev_ops->destroy (dev);
215 }
216 
217 void
ped_device_cache_remove(PedDevice * dev)218 ped_device_cache_remove(PedDevice *dev)
219 {
220 	_device_unregister (dev);
221 }
222 
223 int
ped_device_is_busy(PedDevice * dev)224 ped_device_is_busy (PedDevice* dev)
225 {
226 	return ped_architecture->dev_ops->is_busy (dev);
227 }
228 
229 /**
230  * Attempt to open a device to allow use of read, write and sync functions.
231  *
232  * The meaning of "open" is architecture-dependent.  Apart from requesting
233  * access to the device from the operating system, it does things like flushing
234  * caches.
235  * \note May allocate resources.  Any resources allocated here will
236  * be freed by a final ped_device_close().  (ped_device_open() may be
237  * called multiple times -- it's a ref-count-like mechanism)
238  *
239  * \return zero on failure
240  */
241 int
ped_device_open(PedDevice * dev)242 ped_device_open (PedDevice* dev)
243 {
244 	int	status;
245 
246 	PED_ASSERT (dev != NULL, return 0);
247 	PED_ASSERT (!dev->external_mode, return 0);
248 
249 	if (dev->open_count)
250 		status = ped_architecture->dev_ops->refresh_open (dev);
251 	else
252 		status = ped_architecture->dev_ops->open (dev);
253 	if (status)
254 		dev->open_count++;
255 	return status;
256 }
257 
258 /**
259  * Close dev.
260  * If this is the final close, then resources allocated by
261  * ped_device_open() are freed.
262  *
263  * \return zero on failure
264  */
265 int
ped_device_close(PedDevice * dev)266 ped_device_close (PedDevice* dev)
267 {
268 	PED_ASSERT (dev != NULL, return 0);
269 	PED_ASSERT (!dev->external_mode, return 0);
270 	PED_ASSERT (dev->open_count > 0, return 0);
271 
272 	if (--dev->open_count)
273 		return ped_architecture->dev_ops->refresh_close (dev);
274 	else
275 		return ped_architecture->dev_ops->close (dev);
276 }
277 
278 /**
279  * Begins external access mode.  External access mode allows you to
280  * safely do IO on the device.  If a PedDevice is open, then you should
281  * not do any IO on that device, e.g. by calling an external program
282  * like e2fsck, unless you put it in external access mode.  You should
283  * not use any libparted commands that do IO to a device, e.g.
284  * ped_file_system_{open|resize|copy}, ped_disk_{read|write}), while
285  * a device is in external access mode.
286  * Also, you should not ped_device_close() a device, while it is
287  * in external access mode.
288  * Note: ped_device_begin_external_access_mode() does things like
289  * tell the kernel to flush its caches.
290  *
291  * Close a device while pretending it is still open.
292  * This is useful for temporarily suspending libparted access to the device
293  * in order for an external program to access it.
294  * (Running external programs while the device is open can cause cache
295  * coherency problems.)
296  *
297  * In particular, this function keeps track of dev->open_count, so that
298  * reference counting isn't screwed up.
299  *
300  * \return zero on failure.
301  */
302 int
ped_device_begin_external_access(PedDevice * dev)303 ped_device_begin_external_access (PedDevice* dev)
304 {
305 	PED_ASSERT (dev != NULL, return 0);
306 	PED_ASSERT (!dev->external_mode, return 0);
307 
308 	dev->external_mode = 1;
309 	if (dev->open_count)
310 		return ped_architecture->dev_ops->close (dev);
311 	else
312 		return 1;
313 }
314 
315 /**
316  * \brief Complementary function to ped_device_begin_external_access.
317  *
318  * \note does things like tell the kernel to flush the device's cache.
319  *
320  * \return zero on failure.
321  */
322 int
ped_device_end_external_access(PedDevice * dev)323 ped_device_end_external_access (PedDevice* dev)
324 {
325 	PED_ASSERT (dev != NULL, return 0);
326 	PED_ASSERT (dev->external_mode, return 0);
327 
328 	dev->external_mode = 0;
329 	if (dev->open_count)
330 		return ped_architecture->dev_ops->open (dev);
331 	else
332 		return 1;
333 }
334 
335 /**
336  * \internal Read count sectors from dev into buffer, beginning with sector
337  * start.
338  *
339  * \return zero on failure.
340  */
341 int
ped_device_read(const PedDevice * dev,void * buffer,PedSector start,PedSector count)342 ped_device_read (const PedDevice* dev, void* buffer, PedSector start,
343 		 PedSector count)
344 {
345 	PED_ASSERT (dev != NULL, return 0);
346 	PED_ASSERT (buffer != NULL, return 0);
347 	PED_ASSERT (!dev->external_mode, return 0);
348 	PED_ASSERT (dev->open_count > 0, return 0);
349 
350 	return (ped_architecture->dev_ops->read) (dev, buffer, start, count);
351 }
352 
353 /**
354  * \internal Write count sectors from buffer to dev, starting at sector
355  * start.
356  *
357  * \return zero on failure.
358  *
359  * \sa PedDevice::sector_size
360  * \sa PedDevice::phys_sector_size
361  */
362 int
ped_device_write(PedDevice * dev,const void * buffer,PedSector start,PedSector count)363 ped_device_write (PedDevice* dev, const void* buffer, PedSector start,
364 		  PedSector count)
365 {
366 	PED_ASSERT (dev != NULL, return 0);
367 	PED_ASSERT (buffer != NULL, return 0);
368 	PED_ASSERT (!dev->external_mode, return 0);
369 	PED_ASSERT (dev->open_count > 0, return 0);
370 
371 	return (ped_architecture->dev_ops->write) (dev, buffer, start, count);
372 }
373 
374 PedSector
ped_device_check(PedDevice * dev,void * buffer,PedSector start,PedSector count)375 ped_device_check (PedDevice* dev, void* buffer, PedSector start,
376 		  PedSector count)
377 {
378 	PED_ASSERT (dev != NULL, return 0);
379 	PED_ASSERT (!dev->external_mode, return 0);
380 	PED_ASSERT (dev->open_count > 0, return 0);
381 
382 	return (ped_architecture->dev_ops->check) (dev, buffer, start, count);
383 }
384 
385 /**
386  * \internal Flushes all write-behind caches that might be holding up
387  * writes.
388  * It is slow because it guarantees cache coherency among all relevant caches.
389  *
390  * \return zero on failure
391  */
392 int
ped_device_sync(PedDevice * dev)393 ped_device_sync (PedDevice* dev)
394 {
395 	PED_ASSERT (dev != NULL, return 0);
396 	PED_ASSERT (!dev->external_mode, return 0);
397 	PED_ASSERT (dev->open_count > 0, return 0);
398 
399 	return ped_architecture->dev_ops->sync (dev);
400 }
401 
402 /**
403  * \internal Flushes all write-behind caches that might be holding writes.
404  * \warning Does NOT ensure cache coherency with other caches.
405  * If you need cache coherency, use ped_device_sync() instead.
406  *
407  * \return zero on failure
408  */
409 int
ped_device_sync_fast(PedDevice * dev)410 ped_device_sync_fast (PedDevice* dev)
411 {
412 	PED_ASSERT (dev != NULL, return 0);
413 	PED_ASSERT (!dev->external_mode, return 0);
414 	PED_ASSERT (dev->open_count > 0, return 0);
415 
416 	return ped_architecture->dev_ops->sync_fast (dev);
417 }
418 
419 /**
420  * Get a constraint that represents hardware requirements on alignment and
421  * geometry.
422  * This is, for example, important for media that have a physical sector
423  * size that is a multiple of the logical sector size.
424  *
425  * \warning This function is experimental for physical sector sizes not equal to
426  *          2^9.
427  */
428 PedConstraint*
ped_device_get_constraint(PedDevice * dev)429 ped_device_get_constraint (PedDevice* dev)
430 {
431         int multiplier = dev->phys_sector_size / dev->sector_size;
432 
433         PedAlignment* start_align = ped_alignment_new (multiplier, multiplier);
434 
435         PedConstraint* c = ped_constraint_new (
436                                 start_align, ped_alignment_any,
437                                 ped_geometry_new (dev, 0, dev->length),
438                                 ped_geometry_new (dev, 0, dev->length),
439                                 1, dev->length);
440 
441         return c;
442 }
443 
444 /** @} */
445 
446