"Fossies" - the Fresh Open Source Software Archive

Member "dosfstools-4.2/src/io.c" (31 Jan 2021, 4999 Bytes) of package /linux/misc/dosfstools-4.2.tar.gz:


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 "io.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1_vs_4.2.

    1 /* io.c - Virtual disk input/output
    2 
    3    Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
    4    Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
    5    Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
    6    Copyright (C) 2015 Andreas Bombe <aeb@debian.org>
    7 
    8    This program is free software: you can redistribute it and/or modify
    9    it under the terms of the GNU General Public License as published by
   10    the Free Software Foundation, either version 3 of the License, or
   11    (at your option) any later version.
   12 
   13    This program is distributed in the hope that it will be useful,
   14    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   16    GNU General Public License for more details.
   17 
   18    You should have received a copy of the GNU General Public License
   19    along with this program. If not, see <http://www.gnu.org/licenses/>.
   20 
   21    The complete text of the GNU General Public License
   22    can be found in /usr/share/common-licenses/GPL-3 file.
   23 */
   24 
   25 /*
   26  * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
   27  *  Fixed nasty bug that caused every file with a name like
   28  *  xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
   29  */
   30 
   31 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
   32  * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
   33 
   34 #define _LARGEFILE64_SOURCE
   35 #include <stdlib.h>
   36 #include <stdio.h>
   37 #include <string.h>
   38 #include <unistd.h>
   39 #include <sys/types.h>
   40 #include <sys/stat.h>
   41 #include <errno.h>
   42 #include <fcntl.h>
   43 
   44 #include "fsck.fat.h"
   45 #include "common.h"
   46 #include "io.h"
   47 
   48 typedef struct _change {
   49     void *data;
   50     off_t pos;
   51     int size;
   52     struct _change *next;
   53 } CHANGE;
   54 
   55 static CHANGE *changes, *last;
   56 static int fd, did_change = 0;
   57 
   58 
   59 void fs_open(const char *path, int rw)
   60 {
   61     if ((fd = open(path, rw ? O_RDWR : O_RDONLY)) < 0) {
   62     perror("open");
   63     exit(6);
   64     }
   65     changes = last = NULL;
   66     did_change = 0;
   67 }
   68 
   69 /**
   70  * Read data from the partition, accounting for any pending updates that are
   71  * queued for writing.
   72  *
   73  * @param[in]   pos     Byte offset, relative to the beginning of the partition,
   74  *                      at which to read
   75  * @param[in]   size    Number of bytes to read
   76  * @param[out]  data    Where to put the data read
   77  */
   78 void fs_read(off_t pos, int size, void *data)
   79 {
   80     CHANGE *walk;
   81     int got;
   82 
   83     if (lseek(fd, pos, 0) != pos)
   84     pdie("Seek to %lld", (long long)pos);
   85     if ((got = read(fd, data, size)) < 0)
   86     pdie("Read %d bytes at %lld", size, (long long)pos);
   87     if (got != size)
   88     die("Got %d bytes instead of %d at %lld", got, size, (long long)pos);
   89     for (walk = changes; walk; walk = walk->next) {
   90     if (walk->pos < pos + size && walk->pos + walk->size > pos) {
   91         if (walk->pos < pos)
   92         memcpy(data, (char *)walk->data + pos - walk->pos,
   93                min(size, walk->size - pos + walk->pos));
   94         else
   95         memcpy((char *)data + walk->pos - pos, walk->data,
   96                min(walk->size, size + pos - walk->pos));
   97     }
   98     }
   99 }
  100 
  101 int fs_test(off_t pos, int size)
  102 {
  103     void *scratch;
  104     int okay;
  105 
  106     if (lseek(fd, pos, 0) != pos)
  107     pdie("Seek to %lld", (long long)pos);
  108     scratch = alloc(size);
  109     okay = read(fd, scratch, size) == size;
  110     free(scratch);
  111     return okay;
  112 }
  113 
  114 void fs_write(off_t pos, int size, void *data)
  115 {
  116     CHANGE *new;
  117     int did;
  118 
  119     if (write_immed) {
  120     did_change = 1;
  121     if (lseek(fd, pos, 0) != pos)
  122         pdie("Seek to %lld", (long long)pos);
  123     if ((did = write(fd, data, size)) == size)
  124         return;
  125     if (did < 0)
  126         pdie("Write %d bytes at %lld", size, (long long)pos);
  127     die("Wrote %d bytes instead of %d at %lld", did, size, (long long)pos);
  128     }
  129     new = alloc(sizeof(CHANGE));
  130     new->pos = pos;
  131     memcpy(new->data = alloc(new->size = size), data, size);
  132     new->next = NULL;
  133     if (last)
  134     last->next = new;
  135     else
  136     changes = new;
  137     last = new;
  138 }
  139 
  140 static void fs_flush(void)
  141 {
  142     CHANGE *this;
  143     int size;
  144 
  145     while (changes) {
  146     this = changes;
  147     changes = changes->next;
  148     if (lseek(fd, this->pos, 0) != this->pos)
  149         fprintf(stderr,
  150             "Seek to %lld failed: %s\n  Did not write %d bytes.\n",
  151             (long long)this->pos, strerror(errno), this->size);
  152     else if ((size = write(fd, this->data, this->size)) < 0)
  153         fprintf(stderr, "Writing %d bytes at %lld failed: %s\n", this->size,
  154             (long long)this->pos, strerror(errno));
  155     else if (size != this->size)
  156         fprintf(stderr, "Wrote %d bytes instead of %d bytes at %lld."
  157             "\n", size, this->size, (long long)this->pos);
  158     free(this->data);
  159     free(this);
  160     }
  161 }
  162 
  163 int fs_close(int write)
  164 {
  165     CHANGE *next;
  166     int changed;
  167 
  168     changed = ! !changes;
  169     if (write)
  170     fs_flush();
  171     else
  172     while (changes) {
  173         next = changes->next;
  174         free(changes->data);
  175         free(changes);
  176         changes = next;
  177     }
  178     if (close(fd) < 0)
  179     pdie("closing filesystem");
  180     return changed || did_change;
  181 }
  182 
  183 int fs_changed(void)
  184 {
  185     return ! !changes || did_change;
  186 }