embox

Форк
0
/
iso9660_file_ops.c 
295 строк · 5.9 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @date 20.08.2012
6
 * @author Andrey Gazukin
7
 */
8

9
#include <time.h>
10
#include <ctype.h>
11
#include <string.h>
12
#include <fcntl.h>
13
#include <errno.h>
14

15
#include <util/err.h>
16

17
#include <drivers/block_dev.h>
18

19
#include <fs/inode.h>
20
#include <fs/super_block.h>
21
#include <fs/iso9660.h>
22

23
#include <fs/file_desc.h>
24

25
extern int cdfs_isonum_711(unsigned char *p);
26
extern int cdfs_isonum_733(unsigned char *p);
27
extern time_t cdfs_isodate(unsigned char *date);
28

29
extern int cdfs_find_file(struct cdfs_fs_info *cdfs, char *name, int len,
30
							iso_directory_record_t **rec);
31

32
#if 0
33
static int cdfs_open(struct inode *node, char *name) {
34
	iso_directory_record_t *rec;
35
	time_t date;
36
	int size;
37
	int extent;
38
	int flags;
39
	int rc;
40
	struct cdfs_file_info *fi;
41
	struct cdfs_fs_info *fsi;
42

43
	fi = inode_priv(node);
44
	fsi = node->i_sb->sb_data;;
45

46
	/* Check open mode */
47
	if (fi->flags & (O_CREAT | O_TRUNC | O_APPEND)) {
48
		return -EROFS;
49
	}
50

51
	for(int i = 0; name[i]; i++){
52
		name[i] = toupper(name[i]);
53
	}
54

55
	/* Locate file in file system */
56
	rc = cdfs_find_file(fsi, name, strlen(name), &rec);
57
	if (rc < 0) {
58
		return rc;
59
	}
60

61
	flags = cdfs_isonum_711(rec->flags);
62
	extent = cdfs_isonum_733(rec->extent);
63
	date = cdfs_isodate(rec->date);
64
	size = cdfs_isonum_733(rec->size);
65

66
	fi->extent = extent;
67
	fi->date = date;
68
	fi->size = size;
69
	if (flags & 2) {
70
		//fi->flags |= F_DIR;
71
		fi->flags |= S_IFDIR;
72
	}
73

74
//	fi->mode = S_IFREG | S_IRUSR | S_IXUSR |
75
//	   S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
76
	return 0;
77
}
78
#endif
79

80
static int cdfs_read(struct inode *node, void *data, size_t size, int64_t pos) {
81
	size_t read;
82
	size_t count;
83
	size_t left;
84
	char *p;
85
	int iblock;
86
	int start;
87
	int blk;
88
	struct block_dev_cache *cache;
89
	struct cdfs_file_info *fi;
90
	struct cdfs_fs_info *fsi;
91

92
	fi = inode_priv(node);
93
	fsi = node->i_sb->sb_data;
94

95
	read = 0;
96
	p = (char *) data;
97
	while (pos < fi->size && size > 0) {
98
		iblock = (int) pos / CDFS_BLOCKSIZE;
99
		start = (int) pos % CDFS_BLOCKSIZE;
100

101
		count = CDFS_BLOCKSIZE - start;
102
		if (count > size) {
103
			count = size;
104
		}
105

106
		left = fi->size - (int) pos;
107
		if (count > left) {
108
			count = left;
109
		}
110
		if (count <= 0) {
111
			break;
112
		}
113

114
		blk = fi->extent + iblock;
115

116
		if (fi->flags & O_DIRECT) {
117
			if (start != 0 || count != CDFS_BLOCKSIZE) {
118
				return read;
119
			}
120
			if (block_dev_read(fsi->bdev, p, count, blk) != (int) count) {
121
				return read;
122
			}
123
		}
124
		else {
125
			cache = block_dev_cached_read(fsi->bdev, blk);
126
			if (!cache) {
127
				return -EIO;
128
			}
129
			memcpy(p, cache->data + start, count);
130
		}
131

132
		pos += count;
133
		p += count;
134
		read += count;
135
		size -= count;
136
	}
137

138
	return read;
139
}
140

141
/*
142
static int cdfs_opendir(struct inode *dir_node, char *name) {
143
	struct cdfs *cdfs;
144
	iso_directory_record_t *rec;
145
	cdfs_file_t *cdfile;
146
	time_t date;
147
	int size;
148
	int extent;
149
	int flags;
150
	int rc;
151
	struct cdfs_file_info *fi;
152

153
	fi = inode_priv(dir->node);
154
	cdfs = (struct cdfs *) dir_node->i_sb->data;
155

156
	// Locate directory
157
	rc = cdfs_find_file(cdfs, name, strlen(name), &rec);
158
	if (rc < 0) {
159
		return rc;
160
	}
161

162
	flags = cdfs_isonum_711(rec->flags);
163
	extent = cdfs_isonum_733(rec->extent);
164
	date = cdfs_isodate(rec->date);
165
	size = cdfs_isonum_733(rec->size);
166

167
	if (!(flags & 2)) {
168
		return -ENOTDIR;
169
	}
170

171
	// Allocate and initialize file block
172
	cdfile = (cdfs_file_t *) sysmalloc(sizeof(cdfs_file_t));
173
	if (!cdfile) {
174
		return -ENOMEM;
175
	}
176
	cdfile->extent = extent;
177
	cdfile->date = date;
178
	cdfile->size = size;
179

180
	fi->data = cdfile;
181
	fi->mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP |
182
				 S_IXGRP | S_IROTH | S_IXOTH;
183
	return 0;
184
}
185

186
static int cdfs_readdir(struct inode *node, direntry_t *dirp, int count) {
187
	cdfs_file_t *cdfile;
188
	struct cdfs *cdfs;
189
	iso_directory_record_t *rec;
190
	struct block_dev_cache *cache;
191
	int namelen;
192
	int reclen;
193
	int blkleft;
194
	char *name;
195
	wchar_t *wname;
196
	struct cdfs_file_info *fi;
197

198
	fi = inode_priv(node);
199
	cdfile = (cdfs_file_t *) fi->data;
200
	cdfs = (struct cdfs *) node->i_sb->data;
201

202
  blkagain:
203
	if (count != 1) {
204
		return -EINVAL;
205
	}
206
	if (fi->pos >= cdfile->size) {
207
		return 0;
208
	}
209

210
	// Get directory block
211
	cache = block_dev_cached_read(cdfs->bdev, cdfile->extent +
212
			(int) fi->pos / CDFS_BLOCKSIZE);
213
	if (!cache) {
214
		return -EIO;
215
	}
216

217
	// Locate directory record
218
  recagain:
219
	rec = (iso_directory_record_t *) (cache->data +
220
			(int) fi->pos % CDFS_BLOCKSIZE);
221
	reclen = cdfs_isonum_711(rec->length);
222
	namelen = cdfs_isonum_711(rec->name_len);
223

224
	// Check for no more records in block
225
	if (reclen == 0) {
226
		blkleft = CDFS_BLOCKSIZE - ((int) fi->pos % CDFS_BLOCKSIZE);
227
		fi->pos += blkleft;
228
		goto blkagain;
229
	}
230

231
	 // Check for . and .. entries /
232
	if (namelen == 1 && (rec->name[0] == 0 || rec->name[0] == 1)) {
233
		fi->pos += reclen;
234
		goto recagain;
235
	}
236

237
	// Get info from directory record /
238
	dirp->ino = cdfs_isonum_733(rec->extent);
239
	dirp->reclen = sizeof(direntry_t) - PATH_MAX + namelen + 1;
240
	if (cdfs->joliet) {
241
		namelen /= 2;
242
		wname = (wchar_t *) rec->name;
243
		if (namelen > 1 && ntohs(wname[namelen - 2]) == ';') {
244
			namelen -= 2;
245
		}
246
		if (namelen > 0 && ntohs(wname[namelen - 1]) == '.') {
247
			namelen -= 1;
248
		}
249

250
		dirp->namelen = namelen;
251
		for (int n = 0; n < namelen; n++) {
252
			dirp->name[n] = (char) ntohs(wname[n]);
253
		}
254
		dirp->name[namelen] = 0;
255
	}
256
	else {
257
		name = (char *) rec->name;
258
		if (namelen > 1 && name[namelen - 2] == ';') namelen -= 2;
259
		if (namelen > 0 && name[namelen - 1] == '.') namelen -= 1;
260

261
		dirp->namelen = namelen;
262
		memcpy(dirp->name, name, namelen);
263
		dirp->name[namelen] = 0;
264
	}
265

266
	fi->pos += reclen;
267
	return 1;
268
}
269

270
*/
271

272
/* File operations */
273
static int    cdfsfs_close(struct file_desc *desc);
274
static size_t cdfsfs_read(struct file_desc *desc, void *buf, size_t size);
275

276
static int cdfsfs_close(struct file_desc *desc) {
277
	return 0;
278
}
279

280
static size_t cdfsfs_read(struct file_desc *desc, void *buf, size_t size) {
281
	int rezult;
282
	struct cdfs_file_info *fi;
283

284
	fi = inode_priv(desc->f_inode);
285

286
	rezult = cdfs_read(desc->f_inode, (void *) buf, size, fi->pos);
287
	fi->pos += rezult;
288

289
	return rezult;
290
}
291

292
struct file_operations cdfsfs_fop = {
293
	.close = cdfsfs_close,
294
	.read = cdfsfs_read,
295
};
296

297

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.