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 *
  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
  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
  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*
 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
 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
 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
 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*
 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
 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
 218 ped_device_cache_remove(PedDevice *dev)
 219 {
 220         _device_unregister (dev);
 221 }
 222 
 223 int
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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*
 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