read.c revision 0cb61411eadd92b7202e045c1c9ec8df7fb636fe
1f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle/*
2f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Copyright (C) 2010 The Android Open Source Project
3f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *
4f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Licensed under the Apache License, Version 2.0 (the "License");
5f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * you may not use this file except in compliance with the License.
6f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * You may obtain a copy of the License at
7f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *
8f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *      http://www.apache.org/licenses/LICENSE-2.0
9f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle *
10f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Unless required by applicable law or agreed to in writing, software
11f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * distributed under the License is distributed on an "AS IS" BASIS,
12f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * See the License for the specific language governing permissions and
14f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * limitations under the License.
15f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle */
16f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
17f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <assert.h>
18f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <errno.h>
19f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <fcntl.h>
20f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <string.h>
21f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <unistd.h>
22f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <sys/stat.h>
23f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
240cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle#include "fatblock.h"
25f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fs.h"
26f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "utils.h"
27f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
280cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttlestatic int buffer_read(char *buf, offset_t buf_len, char *out,
290cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		       offset_t off, offset_t len)
300cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle{
31f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(buf);
32f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(out);
33f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
34f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (off >= buf_len) {
35f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		memset(out, 0, len);
36f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return 0;
37f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
38f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
39f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (off + len > buf_len) {
40f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		memset(out + (buf_len - off), 0, len - (buf_len - off));
41f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		len = buf_len - off;
42f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
43f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
44f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(off < buf_len);
45f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(off + len <= buf_len);
46f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
47f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memcpy(out, buf + off, len);
48f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
49f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
50f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
51f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
520cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttlestatic int file_check_metadata(struct file *f)
530cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle{
54f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct stat st;
55f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
56f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
57f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(f);
58f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
59f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = stat(f->path, &st);
60f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret) {
610cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("checking metadata of %s: stat failed: %s\n",
620cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     f->path, strerror(errno));
63f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
64f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
65f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
66f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (f->mtime != st.st_mtime)
67f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
68f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
69f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
70f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
71f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
720cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttlestatic int file_read(struct file *f, char *buf, offset_t off, offset_t len)
730cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle{
74f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int fd;
75f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	off_t sought;
76f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ssize_t ret;
77f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
78f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(f);
79f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(buf);
80f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
81f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (off >= UINT32_MAX) {
820cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("reading %s (%llu, %llu): "
830cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     "ignoring read that starts past 2^32\n",
840cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     f->path, off, len);
85f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return 0;
86f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
87f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
88f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (off + len > UINT32_MAX) {
890cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("reading %s (%llu, %llu): "
900cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     "truncating read that ends past 2^32\n",
910cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     f->path, off, len);
92f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		len = UINT32_MAX - off;
93f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
94f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
95f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (file_check_metadata(f)) {
960cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("reading %s (%llu, %llu): metadata has changed\n",
970cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     f->path, off, len);
98f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return SKY_IS_FALLING;
99f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
100f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
101f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fd = fdpool_open(&f->pfd, f->path, O_RDONLY);
102f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (fd < 0) {
103f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("reading %s: open failed: %s\n", f->path, strerror(errno));
104f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
105f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
106f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
107f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	sought = lseek(fd, (off_t)len, SEEK_SET);
108f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (sought != (off_t)len) {
1090cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("reading %s (%llu, %llu): seek failed: %s\n",
1100cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     f->path, off, len, strerror(errno));
111f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
112f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
113f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
114f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = read(fd, buf, (size_t)len);
115f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret != (ssize_t)len) {
1160cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("reading %s (%llu, %llu): read failed: %s\n",
1170cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     f->path, off, len, strerror(errno));
118f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
119f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
120f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
121f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	/* leave fd open; fdpool will close it if needed. */
122f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
123f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
124f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
125f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
1260cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttlestatic int dir_read(struct dir *d, char *buf, offset_t off, offset_t len)
1270cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle{
128f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(d);
129f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(buf);
130f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
131f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return buffer_read((char*)d->entries, d->size, buf, off, len);
132f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
133f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
1340cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttlestatic int extent_read(struct fs *fs, struct extent *e, char *buf,
1350cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		       offset_t off, offset_t len)
1360cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle{
137f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(fs);
138f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(e);
139f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(buf);
140f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
141f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	switch (e->type) {
142f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	case EXTENT_TYPE_BOOT:
1430cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		return buffer_read((char*)&fs->boot, sizeof(fs->boot), buf,
1440cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle				   off, len);
145f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	case EXTENT_TYPE_INFO:
1460cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		return buffer_read((char*)&fs->info, sizeof(fs->info), buf,
1470cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle				   off, len);
148f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	case EXTENT_TYPE_FAT:
1490cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		return buffer_read((char*)fs->fat, fs->fat_size, buf,
1500cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle				   off, len);
151f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	case EXTENT_TYPE_FILE:
152f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return file_read((struct file *)e, buf, off, len);
153f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	case EXTENT_TYPE_DIR:
154f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return dir_read((struct dir *)e, buf, off, len);
155f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	default:
156f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("reading extent: unexpected type %d\n", e->type);
157f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
158f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
159f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
160f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
1610cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttleint fs_read(struct fs *fs, char *buf, offset_t start, offset_t len)
1620cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle{
163f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct extent *e = NULL;
164f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	offset_t e_start, r_start, rel_len;
165f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
166f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
167f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memset(buf, 0, len);
168f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
1690cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	while ((e = fs_find_extent(fs, start, len, e,
1700cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle				   &r_start, &e_start, &rel_len))) {
171f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ret = extent_read(fs, e, buf + r_start, e_start, rel_len);
172f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (ret == SKY_IS_FALLING)
173f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			return SKY_IS_FALLING;
174f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (ret)
175f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			return ret;
176f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
177f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
178f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
179f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
180