io.c

来自「linux dosfs 工具,可以移植到嵌入式系统下检查存储状态下的磁盘状况,修」· C语言 代码 · 共 188 行

C
188
字号
/* io.c  -  Virtual disk input/output *//* Written 1993 by Werner Almesberger *//* * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de> *	Fixed nasty bug that caused every file with a name like *	xxxxxxxx.xxx to be treated as bad name that needed to be fixed. *//* FAT32, VFAT, Atari format support, and various fixes additions May 1998 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <errno.h>#include <fcntl.h>#include <linux/fd.h>#include "dosfsck.h"#include "common.h"#include "io.h"typedef struct _change {    void *data;    loff_t pos;    int size;    struct _change *next;} CHANGE;static CHANGE *changes,*last;static int fd,did_change = 0;unsigned device_no;/* Use the _llseek system call directly, because there (once?) was a bug in * the glibc implementation of it. */#include <linux/unistd.h>#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__/* On alpha, the syscall is simply lseek, because it's a 64 bit system. */static loff_t llseek( int fd, loff_t offset, int whence ){    return lseek(fd, offset, whence);}#else# ifndef __NR__llseek# error _llseek system call not present# endifstatic _syscall5( int, _llseek, uint, fd, ulong, hi, ulong, lo,		  loff_t *, res, uint, wh );static loff_t llseek( int fd, loff_t offset, int whence ){    loff_t actual;    if (_llseek(fd, offset>>32, offset&0xffffffff, &actual, whence) != 0)	return (loff_t)-1;    return actual;}#endifvoid fs_open(char *path,int rw){    struct stat stbuf;        if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)	pdie("open %s",path);    changes = last = NULL;    did_change = 0;    if (fstat(fd,&stbuf) < 0)	pdie("fstat",path);    device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;}void fs_read(loff_t pos,int size,void *data){    CHANGE *walk;    int got;    if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);    if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);    if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos);    for (walk = changes; walk; walk = walk->next) {	if (walk->pos < pos+size && walk->pos+walk->size > pos) {	    if (walk->pos < pos)		memcpy(data,(char *) walk->data+pos-walk->pos,min(size,		  walk->size-pos+walk->pos));	    else memcpy((char *) data+walk->pos-pos,walk->data,min(walk->size,		  size+pos-walk->pos));	}    }}int fs_test(loff_t pos,int size){    void *scratch;    int okay;    if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);    scratch = alloc(size);    okay = read(fd,scratch,size) == size;    free(scratch);    return okay;}void fs_write(loff_t pos,int size,void *data){    CHANGE *new;    int did;    if (write_immed) {	did_change = 1;	if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);	if ((did = write(fd,data,size)) == size) return;	if (did < 0) pdie("Write %d bytes at %lld",size,pos);	die("Wrote %d bytes instead of %d at %lld",did,size,pos);    }    new = alloc(sizeof(CHANGE));    new->pos = pos;    memcpy(new->data = alloc(new->size = size),data,size);    new->next = NULL;    if (last) last->next = new;    else changes = new;    last = new;}static void fs_flush(void){    CHANGE *this;    int size;    while (changes) {	this = changes;	changes = changes->next;	if (llseek(fd,this->pos,0) != this->pos)	    fprintf(stderr,"Seek to %lld failed: %s\n  Did not write %d bytes.\n",	      this->pos,strerror(errno),this->size);	else if ((size = write(fd,this->data,this->size)) < 0)		fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size,		  this->pos,strerror(errno));	    else if (size != this->size)		    fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld."		      "\n",size,this->size,this->pos);	free(this->data);	free(this);    }}int fs_close(int write){    CHANGE *next;    int changed;    changed = !!changes;    if (write) fs_flush();    else while (changes) {	    next = changes->next;	    free(changes->data);	    free(changes);	    changes = next;	}    if (close(fd) < 0) pdie("closing file system");    return changed || did_change;}int fs_changed(void){    return !!changes || did_change;}/* Local Variables: *//* tab-width: 8     *//* End:             */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?