blob: 4dfef5a3357ab031937a41110a12754ab2a6322d [file] [log] [blame]
/* Copyright 2021 Alain Knaff.
* This file is part of mtools.
*
* Mtools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Mtools is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*
* Open filesystem image or device, and push any remapping and/or partitioning layers on it
Buffer read/write module
*/
#include "sysincludes.h"
#include "msdos.h"
#include "mtools.h"
#include "lba.h"
#include "open_image.h"
#include "plain_io.h"
#include "floppyd_io.h"
#include "xdf_io.h"
#include "scsi_io.h"
#include "remap.h"
#include "partition.h"
#include "offset.h"
#include "swap.h"
/*
* Open filesystem image
* out_dev: device descriptor, adapted to current media and context
* dev: initial template device descriptor (not modified)
* name: file name (if applicable)
* maxSize: if set, max size will be returned here
* geomFailureP: if set, geometry failure will be returned here. This means
* that caller should retry again opening the same image read/write
* skip: a bitmask of intermediary layers to skip
* errmsg: any error messages will be returned here
*/
Stream_t *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,
#ifdef USE_XDF
struct xdf_info *xdf_info
#else
void *dummy UNUSEDP
#endif
)
{
Stream_t *Stream=NULL;
int geomFailure=0;
if(out_dev->misc_flags & FLOPPYD_FLAG) {
#ifdef USE_FLOPPYD
Stream = FloppydOpen(out_dev, name, mode,
errmsg, maxSize);
#endif
} else {
#ifdef USE_XDF
Stream = XdfOpen(out_dev, name, mode, errmsg, xdf_info);
if(Stream) {
out_dev->use_2m = 0x7f;
if(maxSize)
*maxSize = max_off_t_31;
}
#endif
if (!Stream) {
Stream = OpenScsi(out_dev, name,
mode,
errmsg, flags, 0,
lockMode,
maxSize);
}
if (!Stream) {
Stream = SimpleFileOpenWithLm(out_dev, dev, name,
mode,
errmsg, flags, 0,
lockMode,
maxSize,
&geomFailure);
}
if(geomFailure) {
if(*geomFailureP)
*geomFailureP=geomFailure;
return NULL;
}
}
if( !Stream)
return NULL;
if(dev->data_map) {
Stream_t *Remapped = Remap(Stream, out_dev, errmsg);
if(Remapped == NULL)
goto exit_0;
Stream = Remapped;
}
if(dev->offset) {
Stream_t *Offset = OpenOffset(Stream, out_dev, dev->offset,
errmsg, maxSize);
if(Offset == NULL)
goto exit_0;
Stream = Offset;
}
if(DO_SWAP(dev)) {
Stream_t *Swap = OpenSwap(Stream);
if(Swap == NULL)
goto exit_0;
Stream = Swap;
}
if((flags & ALWAYS_GET_GEOMETRY) &&
compute_lba_geom_from_tot_sectors(out_dev) < 0)
goto exit_0;
if(dev->partition && !(flags & SKIP_PARTITION)) {
Stream_t *Partition = OpenPartition(Stream, out_dev,
errmsg, maxSize);
if(Partition == NULL)
goto exit_0;
Stream = Partition;
}
return Stream;
exit_0:
FREE(&Stream);
return NULL;
}