1 #define _LARGEFILE_SOURCE
2 #define _LARGEFILE64_SOURCE
3 #define _GNU_SOURCE
4 #include <errno.h>
5 
6 #include "ibm.h"
7 #include "hdd_file.h"
8 
hdd_load_ext(hdd_file_t * hdd,const char * fn,int spt,int hpc,int tracks,int read_only)9 void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks, int read_only)
10 {
11 	if (hdd->f == NULL)
12         {
13 		/* Try to open existing hard disk image */
14 		if (read_only)
15         		hdd->f = fopen64(fn, "rb");
16 		else
17         		hdd->f = fopen64(fn, "rb+");
18 		if (hdd->f == NULL)
19                 {
20 			/* Failed to open existing hard disk image */
21 			if (errno == ENOENT && !read_only)
22                         {
23 				/* Failed because it does not exist,
24 				   so try to create new file */
25 				hdd->f = fopen64(fn, "wb+");
26 				if (hdd->f == NULL)
27                                 {
28 					pclog("Cannot create file '%s': %s",
29 					      fn, strerror(errno));
30 					return;
31 				}
32 			}
33                         else
34                         {
35 				/* Failed for another reason */
36 				pclog("Cannot open file '%s': %s",
37 				      fn, strerror(errno));
38 				return;
39 			}
40 		}
41 	}
42 
43         hdd->spt = spt;
44         hdd->hpc = hpc;
45         hdd->tracks = tracks;
46         hdd->sectors = spt * hpc * tracks;
47         hdd->read_only = read_only;
48 }
49 
hdd_load(hdd_file_t * hdd,int d,const char * fn)50 void hdd_load(hdd_file_t *hdd, int d, const char *fn)
51 {
52         hdd_load_ext(hdd, fn, hdc[d].spt, hdc[d].hpc, hdc[d].tracks, 0);
53 }
54 
hdd_close(hdd_file_t * hdd)55 void hdd_close(hdd_file_t *hdd)
56 {
57         if (hdd->f)
58         {
59                 fclose(hdd->f);
60                 hdd->f = NULL;
61         }
62 }
63 
hdd_read_sectors(hdd_file_t * hdd,int offset,int nr_sectors,void * buffer)64 int hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
65 {
66         off64_t addr;
67         int transfer_sectors = nr_sectors;
68 
69         if ((hdd->sectors - offset) < transfer_sectors)
70                 transfer_sectors = hdd->sectors - offset;
71         addr = (uint64_t)offset * 512;
72 
73         fseeko64(hdd->f, addr, SEEK_SET);
74         fread(buffer, transfer_sectors*512, 1, hdd->f);
75 
76         if (nr_sectors != transfer_sectors)
77                 return 1;
78         return 0;
79 }
80 
hdd_write_sectors(hdd_file_t * hdd,int offset,int nr_sectors,void * buffer)81 int hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
82 {
83         off64_t addr;
84         int transfer_sectors = nr_sectors;
85 
86         if (hdd->read_only)
87                 return 1;
88 
89         if ((hdd->sectors - offset) < transfer_sectors)
90                 transfer_sectors = hdd->sectors - offset;
91         addr = (uint64_t)offset * 512;
92 
93         fseeko64(hdd->f, addr, SEEK_SET);
94         fwrite(buffer, transfer_sectors*512, 1, hdd->f);
95 
96         if (nr_sectors != transfer_sectors)
97                 return 1;
98         return 0;
99 }
100 
hdd_format_sectors(hdd_file_t * hdd,int offset,int nr_sectors)101 int hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors)
102 {
103         off64_t addr;
104         int c;
105         uint8_t zero_buffer[512];
106         int transfer_sectors = nr_sectors;
107 
108         if (hdd->read_only)
109                 return 1;
110 
111         memset(zero_buffer, 0, 512);
112 
113         if ((hdd->sectors - offset) < transfer_sectors)
114                 transfer_sectors = hdd->sectors - offset;
115         addr = (uint64_t)offset * 512;
116         fseeko64(hdd->f, addr, SEEK_SET);
117         for (c = 0; c < transfer_sectors; c++)
118                 fwrite(zero_buffer, 512, 1, hdd->f);
119 
120         if (nr_sectors != transfer_sectors)
121                 return 1;
122         return 0;
123 }
124