1 /* Copyright 1996,1997,1999,2001,2002,2008,2009 Alain Knaff.
2 * This file is part of mtools.
3 *
4 * Mtools is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Mtools is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "sysincludes.h"
19 #include "msdos.h"
20 #include "stream.h"
21
22 int batchmode = 0;
23
limitSizeToOffT(size_t * len,mt_off_t maxLen)24 void limitSizeToOffT(size_t *len, mt_off_t maxLen)
25 {
26 #if SIZEOF_SIZE_T >= SIZEOF_MT_OFF_T
27 if(*len > (size_t) maxLen)
28 #else
29 if(*len > maxLen)
30 #endif
31 *len = (size_t) maxLen;
32 }
33
init_head(Stream_t * Stream,struct Class_t * Class,Stream_t * Next)34 void init_head(Stream_t *Stream, struct Class_t *Class, Stream_t *Next)
35 {
36 Stream->Class = Class;
37 Stream->refs = 1;
38 Stream->Next = Next;
39 }
40
flush_stream(Stream_t * Stream)41 int flush_stream(Stream_t *Stream)
42 {
43 int ret=0;
44 if(!batchmode) {
45 if(Stream->Class->flush)
46 ret |= Stream->Class->flush(Stream);
47 if(Stream->Next)
48 ret |= flush_stream(Stream->Next);
49 }
50 return ret;
51 }
52
copy_stream(Stream_t * Stream)53 Stream_t *copy_stream(Stream_t *Stream)
54 {
55 if(Stream)
56 Stream->refs++;
57 return Stream;
58 }
59
free_stream(Stream_t ** Stream)60 int free_stream(Stream_t **Stream)
61 {
62 int ret=0;
63
64 if(!*Stream)
65 return -1;
66 if(! --(*Stream)->refs){
67 if((*Stream)->Class->flush)
68 ret |= (*Stream)->Class->flush(*Stream);
69 if((*Stream)->Class->freeFunc)
70 ret |= (*Stream)->Class->freeFunc(*Stream);
71 if((*Stream)->Next)
72 ret |= free_stream(&(*Stream)->Next);
73 Free(*Stream);
74 }
75 *Stream = NULL;
76 return ret;
77 }
78
79
80 #define GET_DATA(stream, date, size, type, address) \
81 (stream)->Class->get_data( (stream), (date), (size), (type), (address) )
82
set_geom_pass_through(Stream_t * Stream,device_t * dev,device_t * orig_dev)83 int set_geom_pass_through(Stream_t *Stream, device_t *dev, device_t *orig_dev)
84 {
85 return SET_GEOM(Stream->Next, dev, orig_dev);
86 }
87
set_geom_noop(Stream_t * Stream UNUSEDP,device_t * dev UNUSEDP,device_t * orig_dev UNUSEDP)88 int set_geom_noop(Stream_t *Stream UNUSEDP,
89 device_t *dev UNUSEDP,
90 device_t *orig_dev UNUSEDP)
91 {
92 return 0;
93 }
94
get_data_pass_through(Stream_t * Stream,time_t * date,mt_off_t * size,int * type,uint32_t * address)95 int get_data_pass_through(Stream_t *Stream, time_t *date, mt_off_t *size,
96 int *type, uint32_t *address)
97 {
98 return GET_DATA(Stream->Next, date, size, type, address);
99 }
100
pread_pass_through(Stream_t * Stream,char * buf,mt_off_t start,size_t len)101 ssize_t pread_pass_through(Stream_t *Stream, char *buf,
102 mt_off_t start, size_t len)
103 {
104 return PREADS(Stream->Next, buf, start, len);
105 }
106
pwrite_pass_through(Stream_t * Stream,char * buf,mt_off_t start,size_t len)107 ssize_t pwrite_pass_through(Stream_t *Stream, char *buf,
108 mt_off_t start, size_t len)
109 {
110 return PWRITES(Stream->Next, buf, start, len);
111 }
112
get_dosConvert_pass_through(Stream_t * Stream)113 doscp_t *get_dosConvert_pass_through(Stream_t *Stream)
114 {
115 return GET_DOSCONVERT(Stream->Next);
116 }
117
118 /*
119 * Adjust number of total sectors by given offset in bytes
120 */
adjust_tot_sectors(struct device * dev,mt_off_t offset,char * errmsg)121 int adjust_tot_sectors(struct device *dev, mt_off_t offset, char *errmsg)
122 {
123 if(!dev->tot_sectors)
124 /* tot_sectors not set, do nothing */
125 return 0;
126
127 mt_off_t offs_sectors = offset /
128 (dev->sector_size ? dev->sector_size : 512);
129 if(offs_sectors > 0 && dev->tot_sectors < (smt_off_t) offs_sectors) {
130 if(errmsg)
131 sprintf(errmsg,"init: Offset bigger than base image");
132 return -1;
133 }
134 dev->tot_sectors -= (uint32_t) offs_sectors;
135 return 0;
136 }
137