"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/utils_io.c" (13 Jan 2022, 7024 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "utils_io.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.3.6_vs_2.4.0.

    1 /*
    2  * utils - miscellaneous I/O utilities for cryptsetup
    3  *
    4  * Copyright (C) 2004 Jana Saout <jana@saout.de>
    5  * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
    6  * Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
    7  * Copyright (C) 2009-2021 Milan Broz
    8  *
    9  * This program is free software; you can redistribute it and/or
   10  * modify it under the terms of the GNU General Public License
   11  * as published by the Free Software Foundation; either version 2
   12  * of the License, or (at your option) any later version.
   13  *
   14  * This program is distributed in the hope that it will be useful,
   15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  * GNU General Public License for more details.
   18  *
   19  * You should have received a copy of the GNU General Public License
   20  * along with this program; if not, write to the Free Software
   21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   22  */
   23 
   24 #include <errno.h>
   25 #include <string.h>
   26 #include <stdlib.h>
   27 #include <stdint.h>
   28 #include <unistd.h>
   29 
   30 #include "utils_io.h"
   31 
   32 static ssize_t _read_buffer(int fd, void *buf, size_t length, volatile int *quit)
   33 {
   34     size_t read_size = 0;
   35     ssize_t r;
   36 
   37     if (fd < 0 || !buf)
   38         return -EINVAL;
   39 
   40     do {
   41         r = read(fd, buf, length - read_size);
   42         if (r == -1 && errno != EINTR)
   43             return r;
   44         if (r > 0) {
   45             read_size += (size_t)r;
   46             buf = (uint8_t*)buf + r;
   47         }
   48         if (r == 0 || (quit && *quit))
   49             return (ssize_t)read_size;
   50     } while (read_size != length);
   51 
   52     return (ssize_t)length;
   53 }
   54 
   55 ssize_t read_buffer(int fd, void *buf, size_t length)
   56 {
   57     return _read_buffer(fd, buf, length, NULL);
   58 }
   59 
   60 ssize_t read_buffer_intr(int fd, void *buf, size_t length, volatile int *quit)
   61 {
   62     return _read_buffer(fd, buf, length, quit);
   63 }
   64 
   65 static ssize_t _write_buffer(int fd, const void *buf, size_t length, volatile int *quit)
   66 {
   67     size_t write_size = 0;
   68     ssize_t w;
   69 
   70     if (fd < 0 || !buf || !length)
   71         return -EINVAL;
   72 
   73     do {
   74         w = write(fd, buf, length - write_size);
   75         if (w < 0 && errno != EINTR)
   76             return w;
   77         if (w > 0) {
   78             write_size += (size_t) w;
   79             buf = (const uint8_t*)buf + w;
   80         }
   81         if (w == 0 || (quit && *quit))
   82             return (ssize_t)write_size;
   83     } while (write_size != length);
   84 
   85     return (ssize_t)write_size;
   86 }
   87 
   88 ssize_t write_buffer(int fd, const void *buf, size_t length)
   89 {
   90     return _write_buffer(fd, buf, length, NULL);
   91 }
   92 
   93 ssize_t write_buffer_intr(int fd, const void *buf, size_t length, volatile int *quit)
   94 {
   95     return _write_buffer(fd, buf, length, quit);
   96 }
   97 
   98 ssize_t write_blockwise(int fd, size_t bsize, size_t alignment,
   99             void *orig_buf, size_t length)
  100 {
  101     void *hangover_buf = NULL, *buf = NULL;
  102     size_t hangover, solid;
  103     ssize_t r, ret = -1;
  104 
  105     if (fd == -1 || !orig_buf || !bsize || !alignment)
  106         return -1;
  107 
  108     hangover = length % bsize;
  109     solid = length - hangover;
  110 
  111     if ((size_t)orig_buf & (alignment - 1)) {
  112         if (posix_memalign(&buf, alignment, length))
  113             return -1;
  114         memcpy(buf, orig_buf, length);
  115     } else
  116         buf = orig_buf;
  117 
  118     if (solid) {
  119         r = write_buffer(fd, buf, solid);
  120         if (r < 0 || r != (ssize_t)solid)
  121             goto out;
  122     }
  123 
  124     if (hangover) {
  125         if (posix_memalign(&hangover_buf, alignment, bsize))
  126             goto out;
  127         memset(hangover_buf, 0, bsize);
  128 
  129         r = read_buffer(fd, hangover_buf, bsize);
  130         if (r < 0)
  131             goto out;
  132 
  133         if (lseek(fd, -(off_t)r, SEEK_CUR) < 0)
  134             goto out;
  135 
  136         memcpy(hangover_buf, (char*)buf + solid, hangover);
  137 
  138         r = write_buffer(fd, hangover_buf, bsize);
  139         if (r < 0 || r < (ssize_t)hangover)
  140             goto out;
  141     }
  142     ret = length;
  143 out:
  144     free(hangover_buf);
  145     if (buf != orig_buf)
  146         free(buf);
  147     return ret;
  148 }
  149 
  150 ssize_t read_blockwise(int fd, size_t bsize, size_t alignment,
  151                void *orig_buf, size_t length)
  152 {
  153     void *hangover_buf = NULL, *buf = NULL;
  154     size_t hangover, solid;
  155     ssize_t r, ret = -1;
  156 
  157     if (fd == -1 || !orig_buf || !bsize || !alignment)
  158         return -1;
  159 
  160     hangover = length % bsize;
  161     solid = length - hangover;
  162 
  163     if ((size_t)orig_buf & (alignment - 1)) {
  164         if (posix_memalign(&buf, alignment, length))
  165             return -1;
  166     } else
  167         buf = orig_buf;
  168 
  169     r = read_buffer(fd, buf, solid);
  170     if (r < 0 || r != (ssize_t)solid)
  171         goto out;
  172 
  173     if (hangover) {
  174         if (posix_memalign(&hangover_buf, alignment, bsize))
  175             goto out;
  176         r = read_buffer(fd, hangover_buf, bsize);
  177         if (r <  0 || r < (ssize_t)hangover)
  178             goto out;
  179 
  180         memcpy((char *)buf + solid, hangover_buf, hangover);
  181     }
  182     ret = length;
  183 out:
  184     free(hangover_buf);
  185     if (buf != orig_buf) {
  186         if (ret != -1)
  187             memcpy(orig_buf, buf, length);
  188         free(buf);
  189     }
  190     return ret;
  191 }
  192 
  193 /*
  194  * Combines llseek with blockwise write. write_blockwise can already deal with short writes
  195  * but we also need a function to deal with short writes at the start. But this information
  196  * is implicitly included in the read/write offset, which can not be set to non-aligned
  197  * boundaries. Hence, we combine llseek with write.
  198  */
  199 ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment,
  200                   void *buf, size_t length, off_t offset)
  201 {
  202     void *frontPadBuf = NULL;
  203     size_t frontHang, innerCount = 0;
  204     ssize_t r, ret = -1;
  205 
  206     if (fd == -1 || !buf || !bsize || !alignment)
  207         return -1;
  208 
  209     if (offset < 0)
  210         offset = lseek(fd, offset, SEEK_END);
  211 
  212     if (offset < 0)
  213         return -1;
  214 
  215     frontHang = offset % bsize;
  216 
  217     if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
  218         return -1;
  219 
  220     if (frontHang && length) {
  221         if (posix_memalign(&frontPadBuf, alignment, bsize))
  222             return -1;
  223 
  224         innerCount = bsize - frontHang;
  225         if (innerCount > length)
  226             innerCount = length;
  227 
  228         r = read_buffer(fd, frontPadBuf, bsize);
  229         if (r < 0 || r < (ssize_t)(frontHang + innerCount))
  230             goto out;
  231 
  232         memcpy((char*)frontPadBuf + frontHang, buf, innerCount);
  233 
  234         if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
  235             goto out;
  236 
  237         r = write_buffer(fd, frontPadBuf, bsize);
  238         if (r < 0 || r != (ssize_t)bsize)
  239             goto out;
  240 
  241         buf = (char*)buf + innerCount;
  242         length -= innerCount;
  243     }
  244 
  245     ret = length ? write_blockwise(fd, bsize, alignment, buf, length) : 0;
  246     if (ret >= 0)
  247         ret += innerCount;
  248 out:
  249     free(frontPadBuf);
  250     return ret;
  251 }
  252 
  253 ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment,
  254                  void *buf, size_t length, off_t offset)
  255 {
  256     void *frontPadBuf = NULL;
  257     size_t frontHang, innerCount = 0;
  258     ssize_t r, ret = -1;
  259 
  260     if (fd == -1 || !buf || bsize <= 0)
  261         return -1;
  262 
  263     if (offset < 0)
  264         offset = lseek(fd, offset, SEEK_END);
  265 
  266     if (offset < 0)
  267         return -1;
  268 
  269     frontHang = offset % bsize;
  270 
  271     if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
  272         return -1;
  273 
  274     if (frontHang && length) {
  275         if (posix_memalign(&frontPadBuf, alignment, bsize))
  276             return -1;
  277 
  278         innerCount = bsize - frontHang;
  279         if (innerCount > length)
  280             innerCount = length;
  281 
  282         r = read_buffer(fd, frontPadBuf, bsize);
  283         if (r < 0 || r < (ssize_t)(frontHang + innerCount))
  284             goto out;
  285 
  286         memcpy(buf, (char*)frontPadBuf + frontHang, innerCount);
  287 
  288         buf = (char*)buf + innerCount;
  289         length -= innerCount;
  290     }
  291 
  292     ret = read_blockwise(fd, bsize, alignment, buf, length);
  293     if (ret >= 0)
  294         ret += innerCount;
  295 out:
  296     free(frontPadBuf);
  297     return ret;
  298 }