00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <unistd.h>
00033 #include <assert.h>
00034 #include <stdint.h>
00035 #include <string.h>
00036 #include <errno.h>
00037 #include <fcntl.h>
00038 #include <err.h>
00039
00040 #include "support.h"
00041 #include "disk.h"
00042
00043 #define HOSTSTRING "System/161 Disk Image"
00044 #define BLOCKSIZE 512
00045
00046 #ifndef EINTR
00047 #define EINTR 0
00048 #endif
00049
00050 static int fd=-1;
00051 static uint32_t nblocks;
00052
00053 void
00054 opendisk(const char *path)
00055 {
00056 struct stat statbuf;
00057
00058 assert(fd<0);
00059 fd = open(path, O_RDWR);
00060 if (fd<0) {
00061 err(1, "%s", path);
00062 }
00063 if (fstat(fd, &statbuf)) {
00064 err(1, "%s: fstat", path);
00065 }
00066
00067 nblocks = statbuf.st_size / BLOCKSIZE;
00068
00069 #ifdef HOST
00070 nblocks--;
00071
00072 {
00073 char buf[64];
00074 int len;
00075
00076 do {
00077 len = read(fd, buf, sizeof(buf)-1);
00078 if (len < 0 && (errno==EINTR || errno==EAGAIN)) {
00079 continue;
00080 }
00081 } while (0);
00082
00083 buf[len] = 0;
00084 buf[strlen(HOSTSTRING)] = 0;
00085
00086 if (strcmp(buf, HOSTSTRING)) {
00087 errx(1, "%s: Not a System/161 disk image", path);
00088 }
00089 }
00090 #endif
00091 }
00092
00093 uint32_t
00094 diskblocksize(void)
00095 {
00096 assert(fd>=0);
00097 return BLOCKSIZE;
00098 }
00099
00100 uint32_t
00101 diskblocks(void)
00102 {
00103 assert(fd>=0);
00104 return nblocks;
00105 }
00106
00107 void
00108 diskwrite(const void *data, uint32_t block)
00109 {
00110 const char *cdata = data;
00111 uint32_t tot=0;
00112 int len;
00113
00114 assert(fd>=0);
00115
00116 #ifdef HOST
00117
00118 block++;
00119 #endif
00120
00121 if (lseek(fd, block*BLOCKSIZE, SEEK_SET)<0) {
00122 err(1, "lseek");
00123 }
00124
00125 while (tot < BLOCKSIZE) {
00126 len = write(fd, cdata + tot, BLOCKSIZE - tot);
00127 if (len < 0) {
00128 if (errno==EINTR || errno==EAGAIN) {
00129 continue;
00130 }
00131 err(1, "write");
00132 }
00133 if (len==0) {
00134 err(1, "write returned 0?");
00135 }
00136 tot += len;
00137 }
00138 }
00139
00140 void
00141 diskread(void *data, uint32_t block)
00142 {
00143 char *cdata = data;
00144 uint32_t tot=0;
00145 int len;
00146
00147 assert(fd>=0);
00148
00149 #ifdef HOST
00150
00151 block++;
00152 #endif
00153
00154 if (lseek(fd, block*BLOCKSIZE, SEEK_SET)<0) {
00155 err(1, "lseek");
00156 }
00157
00158 while (tot < BLOCKSIZE) {
00159 len = read(fd, cdata + tot, BLOCKSIZE - tot);
00160 if (len < 0) {
00161 if (errno==EINTR || errno==EAGAIN) {
00162 continue;
00163 }
00164 err(1, "read");
00165 }
00166 if (len==0) {
00167 err(1, "unexpected EOF in mid-sector");
00168 }
00169 tot += len;
00170 }
00171 }
00172
00173 void
00174 closedisk(void)
00175 {
00176 assert(fd>=0);
00177 if (close(fd)) {
00178 err(1, "close");
00179 }
00180 fd = -1;
00181 }