1*d5c9a868SElliott Hughes /* Copyright 2021 Alain Knaff.
2*d5c9a868SElliott Hughes * This file is part of mtools.
3*d5c9a868SElliott Hughes *
4*d5c9a868SElliott Hughes * Mtools is free software: you can redistribute it and/or modify
5*d5c9a868SElliott Hughes * it under the terms of the GNU General Public License as published by
6*d5c9a868SElliott Hughes * the Free Software Foundation, either version 3 of the License, or
7*d5c9a868SElliott Hughes * (at your option) any later version.
8*d5c9a868SElliott Hughes *
9*d5c9a868SElliott Hughes * Mtools is distributed in the hope that it will be useful,
10*d5c9a868SElliott Hughes * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*d5c9a868SElliott Hughes * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*d5c9a868SElliott Hughes * GNU General Public License for more details.
13*d5c9a868SElliott Hughes *
14*d5c9a868SElliott Hughes * You should have received a copy of the GNU General Public License
15*d5c9a868SElliott Hughes * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
16*d5c9a868SElliott Hughes *
17*d5c9a868SElliott Hughes * Open filesystem image or device, and push any remapping and/or partitioning layers on it
18*d5c9a868SElliott Hughes Buffer read/write module
19*d5c9a868SElliott Hughes */
20*d5c9a868SElliott Hughes
21*d5c9a868SElliott Hughes #include "sysincludes.h"
22*d5c9a868SElliott Hughes #include "msdos.h"
23*d5c9a868SElliott Hughes #include "mtools.h"
24*d5c9a868SElliott Hughes #include "lba.h"
25*d5c9a868SElliott Hughes
26*d5c9a868SElliott Hughes #include "open_image.h"
27*d5c9a868SElliott Hughes
28*d5c9a868SElliott Hughes #include "plain_io.h"
29*d5c9a868SElliott Hughes #include "floppyd_io.h"
30*d5c9a868SElliott Hughes #include "xdf_io.h"
31*d5c9a868SElliott Hughes #include "scsi_io.h"
32*d5c9a868SElliott Hughes #include "remap.h"
33*d5c9a868SElliott Hughes #include "partition.h"
34*d5c9a868SElliott Hughes #include "offset.h"
35*d5c9a868SElliott Hughes #include "swap.h"
36*d5c9a868SElliott Hughes
37*d5c9a868SElliott Hughes /*
38*d5c9a868SElliott Hughes * Open filesystem image
39*d5c9a868SElliott Hughes * out_dev: device descriptor, adapted to current media and context
40*d5c9a868SElliott Hughes * dev: initial template device descriptor (not modified)
41*d5c9a868SElliott Hughes * name: file name (if applicable)
42*d5c9a868SElliott Hughes * maxSize: if set, max size will be returned here
43*d5c9a868SElliott Hughes * geomFailureP: if set, geometry failure will be returned here. This means
44*d5c9a868SElliott Hughes * that caller should retry again opening the same image read/write
45*d5c9a868SElliott Hughes * skip: a bitmask of intermediary layers to skip
46*d5c9a868SElliott Hughes * errmsg: any error messages will be returned here
47*d5c9a868SElliott Hughes */
OpenImage(struct device * out_dev,struct device * dev,const char * name,int mode,char * errmsg,int flags,int lockMode,mt_off_t * maxSize,int * geomFailureP,struct xdf_info * xdf_info)48*d5c9a868SElliott Hughes Stream_t *OpenImage(struct device *out_dev, struct device *dev,
49*d5c9a868SElliott Hughes const char *name, int mode, char *errmsg,
50*d5c9a868SElliott Hughes int flags, int lockMode,
51*d5c9a868SElliott Hughes mt_off_t *maxSize, int *geomFailureP,
52*d5c9a868SElliott Hughes #ifdef USE_XDF
53*d5c9a868SElliott Hughes struct xdf_info *xdf_info
54*d5c9a868SElliott Hughes #else
55*d5c9a868SElliott Hughes void *dummy UNUSEDP
56*d5c9a868SElliott Hughes #endif
57*d5c9a868SElliott Hughes )
58*d5c9a868SElliott Hughes {
59*d5c9a868SElliott Hughes Stream_t *Stream=NULL;
60*d5c9a868SElliott Hughes int geomFailure=0;
61*d5c9a868SElliott Hughes if(out_dev->misc_flags & FLOPPYD_FLAG) {
62*d5c9a868SElliott Hughes #ifdef USE_FLOPPYD
63*d5c9a868SElliott Hughes Stream = FloppydOpen(out_dev, name, mode,
64*d5c9a868SElliott Hughes errmsg, maxSize);
65*d5c9a868SElliott Hughes #endif
66*d5c9a868SElliott Hughes } else {
67*d5c9a868SElliott Hughes
68*d5c9a868SElliott Hughes #ifdef USE_XDF
69*d5c9a868SElliott Hughes Stream = XdfOpen(out_dev, name, mode, errmsg, xdf_info);
70*d5c9a868SElliott Hughes if(Stream) {
71*d5c9a868SElliott Hughes out_dev->use_2m = 0x7f;
72*d5c9a868SElliott Hughes if(maxSize)
73*d5c9a868SElliott Hughes *maxSize = max_off_t_31;
74*d5c9a868SElliott Hughes }
75*d5c9a868SElliott Hughes #endif
76*d5c9a868SElliott Hughes
77*d5c9a868SElliott Hughes if (!Stream) {
78*d5c9a868SElliott Hughes Stream = OpenScsi(out_dev, name,
79*d5c9a868SElliott Hughes mode,
80*d5c9a868SElliott Hughes errmsg, flags, 0,
81*d5c9a868SElliott Hughes lockMode,
82*d5c9a868SElliott Hughes maxSize);
83*d5c9a868SElliott Hughes }
84*d5c9a868SElliott Hughes
85*d5c9a868SElliott Hughes if (!Stream) {
86*d5c9a868SElliott Hughes Stream = SimpleFileOpenWithLm(out_dev, dev, name,
87*d5c9a868SElliott Hughes mode,
88*d5c9a868SElliott Hughes errmsg, flags, 0,
89*d5c9a868SElliott Hughes lockMode,
90*d5c9a868SElliott Hughes maxSize,
91*d5c9a868SElliott Hughes &geomFailure);
92*d5c9a868SElliott Hughes }
93*d5c9a868SElliott Hughes
94*d5c9a868SElliott Hughes if(geomFailure) {
95*d5c9a868SElliott Hughes if(*geomFailureP)
96*d5c9a868SElliott Hughes *geomFailureP=geomFailure;
97*d5c9a868SElliott Hughes return NULL;
98*d5c9a868SElliott Hughes }
99*d5c9a868SElliott Hughes }
100*d5c9a868SElliott Hughes
101*d5c9a868SElliott Hughes if( !Stream)
102*d5c9a868SElliott Hughes return NULL;
103*d5c9a868SElliott Hughes
104*d5c9a868SElliott Hughes if(dev->data_map) {
105*d5c9a868SElliott Hughes Stream_t *Remapped = Remap(Stream, out_dev, errmsg);
106*d5c9a868SElliott Hughes if(Remapped == NULL)
107*d5c9a868SElliott Hughes goto exit_0;
108*d5c9a868SElliott Hughes Stream = Remapped;
109*d5c9a868SElliott Hughes }
110*d5c9a868SElliott Hughes
111*d5c9a868SElliott Hughes if(dev->offset) {
112*d5c9a868SElliott Hughes Stream_t *Offset = OpenOffset(Stream, out_dev, dev->offset,
113*d5c9a868SElliott Hughes errmsg, maxSize);
114*d5c9a868SElliott Hughes if(Offset == NULL)
115*d5c9a868SElliott Hughes goto exit_0;
116*d5c9a868SElliott Hughes Stream = Offset;
117*d5c9a868SElliott Hughes }
118*d5c9a868SElliott Hughes
119*d5c9a868SElliott Hughes if(DO_SWAP(dev)) {
120*d5c9a868SElliott Hughes Stream_t *Swap = OpenSwap(Stream);
121*d5c9a868SElliott Hughes if(Swap == NULL)
122*d5c9a868SElliott Hughes goto exit_0;
123*d5c9a868SElliott Hughes Stream = Swap;
124*d5c9a868SElliott Hughes }
125*d5c9a868SElliott Hughes
126*d5c9a868SElliott Hughes if((flags & ALWAYS_GET_GEOMETRY) &&
127*d5c9a868SElliott Hughes compute_lba_geom_from_tot_sectors(out_dev) < 0)
128*d5c9a868SElliott Hughes goto exit_0;
129*d5c9a868SElliott Hughes
130*d5c9a868SElliott Hughes if(dev->partition && !(flags & SKIP_PARTITION)) {
131*d5c9a868SElliott Hughes Stream_t *Partition = OpenPartition(Stream, out_dev,
132*d5c9a868SElliott Hughes errmsg, maxSize);
133*d5c9a868SElliott Hughes if(Partition == NULL)
134*d5c9a868SElliott Hughes goto exit_0;
135*d5c9a868SElliott Hughes Stream = Partition;
136*d5c9a868SElliott Hughes }
137*d5c9a868SElliott Hughes
138*d5c9a868SElliott Hughes return Stream;
139*d5c9a868SElliott Hughes exit_0:
140*d5c9a868SElliott Hughes FREE(&Stream);
141*d5c9a868SElliott Hughes return NULL;
142*d5c9a868SElliott Hughes }
143*d5c9a868SElliott Hughes
144