]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: add read() based fallback for char (UBI) devs
authorKarel Zak <kzak@redhat.com>
Thu, 24 Sep 2015 08:35:18 +0000 (10:35 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 24 Sep 2015 09:10:09 +0000 (11:10 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/probe.c

index 35a25d20fe874800f5a0a07501c88d449df84037..9f81099598482a513945477029b4f6d081a93b6a 100644 (file)
@@ -588,6 +588,8 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[
 #define PROBE_MMAP_ENDSIZ      (1024 * 1024 * 2)       /* end of the device */
 #define PROBE_MMAP_MIDSIZ      (1024 * 1024)           /* middle of the device */
 
+#define probe_is_mmap_wanted(p)                (!S_ISCHR((p)->mode))
+
 static struct blkid_bufinfo *mmap_buffer(blkid_probe pr,
                                         blkid_loff_t real_off,
                                         blkid_loff_t len)
@@ -660,6 +662,50 @@ static struct blkid_bufinfo *mmap_buffer(blkid_probe pr,
        return bf;
 }
 
+static struct blkid_bufinfo *read_buffer(blkid_probe pr,
+                                        blkid_loff_t real_off,
+                                        blkid_loff_t len)
+{
+       ssize_t ret;
+       struct blkid_bufinfo *bf = NULL;
+
+       if (blkid_llseek(pr->fd, real_off, SEEK_SET) < 0) {
+               errno = 0;
+               return NULL;
+       }
+
+       /* someone trying to overflow some buffers? */
+       if (len > ULONG_MAX - sizeof(struct blkid_bufinfo)) {
+               errno = ENOMEM;
+               return NULL;
+       }
+
+       /* allocate info and space for data by one malloc call */
+       bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
+       if (!bf) {
+               errno = ENOMEM;
+               return NULL;
+       }
+
+       bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
+       bf->len = len;
+       bf->off = real_off;
+       INIT_LIST_HEAD(&bf->bufs);
+
+       DBG(LOWPROBE, ul_debug("\tread %p: off=%jd len=%jd", bf->data, real_off, len));
+
+       ret = read(pr->fd, bf->data, len);
+       if (ret != (ssize_t) len) {
+               DBG(LOWPROBE, ul_debug("\tread failed: %m"));
+               free(bf);
+               if (ret >= 0)
+                       errno = 0;
+               return NULL;
+       }
+
+       return bf;
+}
+
 /*
  * Note that @off is offset within probing area, the probing area is defined by
  * pr->off and pr->size.
@@ -717,7 +763,10 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 
        /* not found; read from disk */
        if (!bf) {
-               bf = mmap_buffer(pr, real_off, len);
+               if (probe_is_mmap_wanted(pr))
+                       bf = mmap_buffer(pr, real_off, len);
+               else
+                       bf = read_buffer(pr, real_off, len);
                if (!bf)
                        return NULL;
 
@@ -733,7 +782,7 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 
 static void blkid_probe_reset_buffer(blkid_probe pr)
 {
-       uint64_t mmap_ct = 0, len_ct = 0;
+       uint64_t ct = 0, len = 0;
 
        if (!pr || list_empty(&pr->buffers))
                return;
@@ -743,17 +792,19 @@ static void blkid_probe_reset_buffer(blkid_probe pr)
        while (!list_empty(&pr->buffers)) {
                struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
                                                struct blkid_bufinfo, bufs);
-               mmap_ct++;
-               len_ct += bf->len;
+               ct++;
+               len += bf->len;
                list_del(&bf->bufs);
 
-               DBG(BUFFER, ul_debug(" unmap: %p [off=%ju, len=%ju]", bf->data, bf->off, bf->len));
-               munmap(bf->data, bf->len);
+               DBG(BUFFER, ul_debug(" remove buffer: %p [off=%ju, len=%ju]", bf->data, bf->off, bf->len));
+
+               if (probe_is_mmap_wanted(pr))
+                       munmap(bf->data, bf->len);
                free(bf);
        }
 
-       DBG(LOWPROBE, ul_debug("buffers summary: %ju bytes (%ju pages) by %ju mmap() call(s)",
-                       len_ct, len_ct / pr->mmap_granularity, mmap_ct));
+       DBG(LOWPROBE, ul_debug(" buffers summary: %ju bytes by %ju read/mmap() calls",
+                       lenct));
 
        INIT_LIST_HEAD(&pr->buffers);
 }
@@ -840,7 +891,7 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
                goto err;
 
        if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode)) {
-                errno = EINVAL;
+               errno = EINVAL;
                goto err;
        }