embox

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

9
#include <string.h>
10

11
#include <fs/inode.h>
12

13
#include <drivers/block_dev.h>
14

15
#include <fs/fs_driver.h>
16
#include <fs/dir_context.h>
17
#include <fs/inode_operation.h>
18
#include <fs/super_block.h>
19

20
#include <fs/iso9660.h>
21

22

23
extern int cdfs_isonum_711(unsigned char *p);
24
extern int cdfs_isonum_733(unsigned char *p);
25

26
extern int cdfs_alloc_inode_priv(struct inode* node);
27
extern int cdfs_destroy_inode(struct inode *inode);
28
extern int cdfs_fill_node(struct inode* node, char *name, struct cdfs_fs_info *cdfs, iso_directory_record_t *rec);
29
extern int cdfs_find_dir(struct cdfs_fs_info *cdfs, char *name, int len);
30

31
extern struct inode *cdfs_ilookup(struct inode *node, char const *name, struct inode const *dir);
32

33
static int cdfs_iterate(struct inode *next, char *next_name, struct inode *parent, struct dir_ctx *dir_ctx) {
34
	int n;
35
	struct cdfs_fs_info *fsi;
36
	struct block_dev_cache *cache;
37
	int blk;
38
	char *p;
39
	iso_directory_record_t *rec;
40
	int left;
41
	int reclen;
42
	int idx = 0;
43
	char *dir_name;
44

45
	fsi = parent->i_sb->sb_data;
46

47
	if (0 == (int) (intptr_t) dir_ctx->fs_ctx) {
48
		dir_ctx->fs_ctx = (void*)(intptr_t)2;
49
	}
50
	if (parent == parent->i_sb->sb_root) {
51
		dir_name = "";
52
	} else {
53
		dir_name = inode_name(parent);
54
	}
55
	n = cdfs_find_dir(fsi, dir_name, strlen(dir_name));
56

57
	/* The first two directory records are . (current) and .. (parent) */
58
	blk = fsi->path_table[n]->extent;
59
	cache = block_dev_cached_read(fsi->bdev, blk++);
60
	if (!cache) {
61
		return -1;
62
	}
63

64
	/* Get length of directory from the first record */
65
	p = cache->data;
66
	rec = (iso_directory_record_t *) p;
67
	left = cdfs_isonum_733(rec->size);
68

69
	/* Find named entry in directory */
70
	while (left > 0) {
71
		/*
72
		 * Read next block if all records in current block has been read
73
		 * Directory records never cross block boundaries
74
		 */
75
		if (p >= cache->data + CDFS_BLOCKSIZE) {
76
			if (p > cache->data + CDFS_BLOCKSIZE) {
77
				return -1;
78
			}
79
			cache = block_dev_cached_read(fsi->bdev, blk++);
80
			if (!cache) {
81
				return -1;
82
			}
83
			p = cache->data;
84
		}
85

86
		/* Check for match */
87
		rec = (iso_directory_record_t *) p;
88
		reclen = cdfs_isonum_711(rec->length);
89

90
		if (reclen > 0) {
91

92
			if (idx++ < (int)(uintptr_t)dir_ctx->fs_ctx) {
93
			} else {
94
				int res;
95

96
				res = cdfs_alloc_inode_priv(next);
97
				if (res) {
98
					return -1;
99
				}
100

101
				res = cdfs_fill_node(next, next_name, fsi, rec);
102
				if (res) {
103
					cdfs_destroy_inode(next);
104
					return -1;
105
				}
106

107
				dir_ctx->fs_ctx = (void *)(uintptr_t)idx;
108
				
109
				return 0;
110
			}
111
			/* Skip to next record */
112
			p += reclen;
113
			left -= reclen;
114
		}
115
		else {
116
			/* Skip to next block */
117
			left -= (cache->data + CDFS_BLOCKSIZE) - p;
118
			p = cache->data + CDFS_BLOCKSIZE;
119
		}
120
	}
121
	return -1;
122
}
123

124
struct inode_operations cdfs_iops = {
125
	.ino_iterate = cdfs_iterate,
126
	.ino_lookup  = cdfs_ilookup,
127
};
128

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

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

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

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