#include #include #include #include #include #include extern const char *__progname; static int cfd; static int ffd; static int ro; static void usage(void) { fprintf(stderr,"Usage: %s pseudo-disk-device backing-file\n",__progname); exit(1); } static int dfdr(void *data, int len) { char *dp; int n; dp = data; while (len > 0) { n = read(cfd,dp,len); if (n <= 0) return(1); dp += n; len -= n; } return(0); } int main(int, char **); int main(int ac, char **av) { unsigned char opc; if (ac != 3) usage(); cfd = open(av[1],O_RDWR,0); if (cfd < 0) { fprintf(stderr,"%s: %s: %s\n",__progname,av[1],strerror(errno)); exit(1); } ro = 0; ffd = open(av[2],O_RDWR,0); if (ffd < 0) { ro = 1; ffd = open(av[2],O_RDONLY,0); if (ffd < 0) { fprintf(stderr,"%s: %s: %s\n",__progname,av[2],strerror(errno)); exit(1); } } while (1) { if (dfdr(&opc,1)) exit(0); switch (opc) { case 'o': { unsigned char args[2]; int err; if (dfdr(&args[0],2)) { fprintf(stderr,"%s: can't read open rwflag/part\n",__progname); exit(1); } switch (args[0]) { case 'r': err = 0; break; case 'w': case 'b': err = ro ? EROFS : 0; break; default: fprintf(stderr,"%s: protocol error: invalid open flag 0x%02x\n",__progname,args[0]); exit(1); break; } write(cfd,&err,sizeof(int)); } break; case 'c': break; case 'r': { unsigned int blkno; char buf[512]; int n; if (dfdr(&blkno,sizeof(unsigned int))) { fprintf(stderr,"%s: can't get read sector #\n",__progname); exit(1); } n = pread(ffd,&buf[0],512,blkno*(off_t)512); if (n < 0) n = errno; else if (n != 512) n = EIO; else n = 0; write(cfd,&n,sizeof(int)); write(cfd,&buf[0],512); } break; case 'w': { char buf[512]; unsigned int blkno; int n; if ( dfdr(&blkno,sizeof(unsigned int)) || dfdr(&buf[0],512) ) { fprintf(stderr,"%s: can't read write packet\n",__progname); exit(1); } n = pwrite(ffd,&buf[0],512,blkno*(off_t)512); if (n < 0) n = errno; else if (n != 512) n = EIO; else n = 0; write(cfd,&n,sizeof(int)); } break; case 'z': { unsigned int l; unsigned int h; unsigned int m; static int ok(unsigned int b) { char junk[512]; return(pread(ffd,&junk[0],512,b*(off_t)512)==512); } l = 0; h = 1; while (ok(l)) { l = h; h <<= 1; } while (h-l > 1) { m = (h + l) >> 1; if (ok(m)) l = m; else h = m; } write(cfd,&h,sizeof(int)); } break; default: fprintf(stderr,"%s: protocol error: invalid command 0x%02x\n",__progname,opc); exit(1); break; } } }