pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


lssparse.c - print sparse file hole+data layout information
Posted by Anonymous on Wed 5th Mar 2025 11:12
raw | new post

  1.  
  2. /*
  3.  * MIT License
  4.  *
  5.  * Copyright (c) 2011-2012 Roland Mainz <roland.mainz@nrubsig.org>
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  8.  * of this software and associated documentation files (the "Software"), to deal
  9.  * in the Software without restriction, including without limitation the rights
  10.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11.  * copies of the Software, and to permit persons to whom the Software is
  12.  * furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in all
  15.  * copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23.  * SOFTWARE.
  24.  */
  25.  
  26. /*
  27.  * lssparse.c - print sparse file hole+data layout information
  28.  *
  29.  * Written by Roland Mainz <roland.mainz@nrubsig.org>
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <stdbool.h>
  35. #include <string.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38. #include <errno.h>
  39.  
  40. #define EXIT_USAGE (2)
  41.  
  42. static
  43. void usage(const char *progname)
  44. {
  45.     (void)fprintf(stderr, "Usage: %s [-h] <sparse_file>\n"
  46.         "  -h: Display this help message\n"
  47.         "  -x: Print offsets in hexadecimal (base 16)\n"
  48.         "  -d: Print offsets in decimal (base 10)\n"
  49.         "  -H: Print hole information\n",
  50.         progname);
  51. }
  52.  
  53. typedef enum _printbase {
  54.     pb_hex = 1,
  55.     pb_dec = 2
  56. } printbase;
  57.  
  58. int main(int argc, char *argv[])
  59. {
  60.     /* Arguments */
  61.     const char *progname = argv[0];
  62.     printbase pb = pb_hex;
  63.     bool print_holes = false;
  64.     const char *filename;
  65.  
  66.     int retval;
  67.     int opt;
  68.     int fd;
  69.  
  70.     size_t i;
  71.     off_t offset = 0;
  72.     off_t data_start;
  73.     off_t hole_start;
  74.     off_t hole_end;
  75.     off_t file_size;
  76.     off_t data_len;
  77.     off_t hole_len;
  78.  
  79.     while ((opt = getopt(argc, argv, "hxdH")) != -1) {
  80.         switch (opt) {
  81.             case '?':
  82.             case 'h':
  83.                 usage(progname);
  84.                 return EXIT_USAGE;
  85.             case 'x':
  86.                 pb = pb_hex;
  87.                 break;
  88.             case 'd':
  89.                 pb = pb_dec;
  90.                 break;
  91.             case 'H':
  92.                 print_holes = true;
  93.                 break;
  94.             default:
  95.                 break;
  96.         }
  97.     }
  98.  
  99.     if (optind >= argc) {
  100.         usage(progname);
  101.         return EXIT_USAGE;
  102.     }
  103.  
  104.     filename = argv[optind];
  105.  
  106.     fd = open(filename, O_RDONLY);
  107.     if (fd == -1) {
  108.         (void)fprintf(stderr, "%s: Open file failed with [%s]\n",
  109.             progname,
  110.             strerror(errno));
  111.         return EXIT_FAILURE;
  112.     }
  113.  
  114.     /* Get file size */
  115.     file_size = lseek(fd, 0, SEEK_END);
  116.     if (file_size == -1) {
  117.         (void)fprintf(stderr, "%s: Cannot seek [%s]\n",
  118.             progname,
  119.             strerror(errno));
  120.         return EXIT_FAILURE;
  121.     }
  122.     (void)lseek(fd, 0, SEEK_SET);
  123.  
  124.  
  125.     /*
  126.      * Loop over hole&&data sections
  127.      *
  128.      * This loop must handle:
  129.      * - normal files with no holes
  130.      * - sparse files which start with data
  131.      * - sparse files which start with a hole
  132.      * - sparse files with multiple holes
  133.      * - sparse files which end with data
  134.      * - sparse files which end with a hole
  135.      *
  136.      * Note we start with index |1| for compatibility
  137.      * with SUN's original sparse file debuggung tools
  138.      * and Win32's
  139.      * $ /cygdrive/c/Windows/system32/fsutil sparse queryrange ... #
  140.      * output
  141.      */
  142.     for (i=1 ;;) {
  143.         data_start = lseek(fd, offset, SEEK_DATA);
  144.         if (data_start == -1)
  145.             break;
  146.         hole_start = lseek(fd, data_start, SEEK_HOLE);
  147.  
  148.         if (hole_start == -1) {
  149.             if (errno == ENXIO) {
  150.                 /* No more holes ? Use file site as pos of next hole */
  151.                 hole_start = file_size;
  152.             } else {
  153.                 (void)fprintf(stderr,
  154.                     "%s: lseek(..., SEEK_HOLE, ...) failed with [%s]\n",
  155.                     progname,
  156.                     strerror(errno));
  157.                     retval = EXIT_FAILURE;
  158.                 goto done;
  159.             }
  160.         }
  161.  
  162.         if (print_holes && (i == 0) && (data_start > 0)) {
  163.             (void)printf((pb == pb_hex)?
  164.                 "Hole range[%ld]: offset=0x%llx,\tlength=0x%llx\n":
  165.                 "Hole range[%ld]: offset=%lld,\tlength=%lld\n",
  166.                 (long)i,
  167.                 (long long)0,
  168.                 (long long)data_start);
  169.             i++;
  170.         }
  171.  
  172.         data_len = hole_start - data_start;
  173.  
  174.         (void)printf((pb == pb_hex)?
  175.             "Data range[%ld]: offset=0x%llx,\tlength=0x%llx\n":
  176.             "Data range[%ld]: offset=%lld,\tlength=%lld\n",
  177.             (long)i,
  178.             (long long)data_start,
  179.             (long long)data_len);
  180.         i++;
  181.  
  182.         hole_end = lseek(fd, hole_start, SEEK_DATA);
  183.  
  184.         if (hole_end == -1) {
  185.             if (errno == ENXIO) {
  186.                 /* No more holes ? */
  187.                 hole_end = file_size;
  188.             } else {
  189.                 (void)fprintf(stderr,
  190.                     "%s: lseek(..., SEEK_DATA, ...) failed with [%s]\n",
  191.                     progname,
  192.                     strerror(errno));
  193.                 retval = EXIT_FAILURE;
  194.                 goto done;
  195.             }
  196.         }
  197.  
  198.         hole_len = hole_end - hole_start;
  199.  
  200.         if (print_holes && (hole_len > 0LL)) {
  201.             (void)printf((pb == pb_hex)?
  202.                 "Hole range[%ld]: offset=0x%llx,\tlength=0x%llx\n":
  203.                 "Hole range[%ld]: offset=%lld,\tlength=%lld\n",
  204.                 (long)i,
  205.                 (long long)hole_start,
  206.                 (long long)hole_len);
  207.             i++;
  208.         }
  209.  
  210.         offset = hole_end;
  211.     }
  212.  
  213.     if ((data_start == -1) && (errno == ENXIO) && (offset == 0)) {
  214.         if (print_holes) {
  215.             (void)printf((pb == pb_hex)?
  216.                 "Hole range[%ld]: offset=0x%llx,\tlength=0x%llx\n":
  217.                 "Hole range[%ld]: offset=%lld,\tlength=%lld\n",
  218.                 (long)0,
  219.                 (long long)0LL,
  220.                 (long long)file_size);
  221.         }
  222.  
  223.         retval = EXIT_SUCCESS;
  224.     } else if ((data_start == -1) && (errno != ENXIO)) {
  225.         (void)fprintf(stderr,
  226.             "%s: lseek(..., SEEK_DATA, ...) failed with [%s]\n",
  227.             progname,
  228.             strerror(errno));
  229.             retval = EXIT_FAILURE;
  230.     }
  231.     else {
  232.         retval = EXIT_SUCCESS;
  233.     }
  234.  
  235. done:
  236.     (void)close(fd);
  237.     return retval;
  238. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at