import.c revision f79b2dff1024db4f6326f3422236bed169dd902f
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 <ctype.h>
19f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <dirent.h>
20f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <errno.h>
21f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <unistd.h>
22f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <stdio.h>
23f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <string.h>
24f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <sys/stat.h>
25f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
26f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "errors.h"
27f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "extent.h"
28f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fat.h"
29f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fdpool.h"
30f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "filedir.h"
31f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fs.h"
32f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "import.h"
33f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "utils.h"
34f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
35f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic inline int valid_char(int c)
36f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
37f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return (isalnum(c) || strchr("!#$%'()-@^_`{}~", c) || ((c >= 128) && (c < 256)));
38f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
39f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
40f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic int convert_name(char *short_name, const char *long_name)
41f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
42f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int i;
43f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
44f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	const char *s;
45f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	const char *dot;
46f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int c;
47f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
48f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	dot = NULL;
49f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
50f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (s = long_name; *s; s++) {
51f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (*s == '.') {
52f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			if (dot) {
53f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				goto short_fail;
54f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			} else {
55f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				dot = s;
56f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			}
57f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		} else if (!valid_char(*s)) {
58f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto short_fail;
59f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
60f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
61f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
62f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (dot - long_name > 8) {
63f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto short_fail;
64f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
65f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
66f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (dot && (s - (dot + 1) > 3)) {
67f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto short_fail;
68f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
69f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
70f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memset(short_name, ' ', 11);
71f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
72f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!dot) {
73f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		dot = s;
74f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
75f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
76f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = 0; i < dot - long_name; i++) {
77f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		short_name[i] = toupper(long_name[i]);
78f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
79f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
80f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = 0; i < s - dot; i++) {
81f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		short_name[8 + i] = toupper(dot[1 + i]);
82f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
83f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
84f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
85f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
86f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleshort_fail:
87f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 1;
88f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
89f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
90f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestruct imported {
91f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t first_cluster;
92f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	uint32_t size;
93f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct fat_dirent *dot_dot_dirent;
94f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle};
95f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
96f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic int import_file(struct fs *fs, char *path, struct imported *out)
97f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
98f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct stat st;
99f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct file *f = NULL;
100f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	char *path_copy = NULL;
101f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
102f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
103f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = stat(path, &st);
104f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret < 0) {
105f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: stat failed: %s\n", path, strerror(errno));
106f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
107f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
108f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
109f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f = malloc(sizeof(struct file));
110f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!f) {
111f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't allocate file struct: out of memory\n", path);
112f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ret = MALLOC_FAIL;
113f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
114f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
115f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
116f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	path_copy = strdup(path);
117f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!path_copy) {
118f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't strdup path: out of memory\n", path);
119f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ret = MALLOC_FAIL;
120f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
121f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
122f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
123f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->path = path_copy;
124f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->size = st.st_size;
125f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->dev = st.st_dev;
126f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->ino = st.st_ino;
127f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->mtime = st.st_mtime;
128f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fdpool_init(&f->pfd);
129f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
130f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = fs_alloc_extent(fs, &f->extent,
131f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                              f->size, EXTENT_TYPE_FILE, &f->first_cluster);
132f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret) {
133f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't allocate data extent\n", path);
134f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
135f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
136f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
137f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	out->first_cluster = f->first_cluster;
138f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	out->size = f->size;
139f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	out->dot_dot_dirent = NULL;
140f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
141f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
142f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
143f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlefail:
144f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (path_copy)
145f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free(path_copy);
146f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (f)
147f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free(f);
148f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return ret;
149f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
150f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
151f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestruct item {
152f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	char name[11];
153f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct imported imp;
154f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *next;
155f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int is_dir;
156f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle};
157f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
158f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic struct item *free_items_head;
159f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
160f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic struct item *alloc_item(void)
161f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
162f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *item;
163f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
164f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (free_items_head) {
165f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = free_items_head;
166f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free_items_head = item->next;
167f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	} else {
168f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = malloc(sizeof(struct item));
169f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		/* May return NULL if item couldn't be allocated. */
170f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
171f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
172f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return item;
173f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
174f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
175f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void free_item(struct item *item)
176f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
177f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	item->next = free_items_head;
178f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free_items_head = item;
179f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
180f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
181f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void free_items(struct item *head)
182f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
183f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *tail;
184f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
185f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (tail = head; tail->next; tail = tail->next);
186f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
187f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	tail->next = free_items_head;
188f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free_items_head = head;
189f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
190f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
191f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle/* TODO: With some work, this can be rewritten so we don't recurse
192f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * until all memory is allocated. */
193f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic int import_dir(struct fs *fs, char *path, int is_root, struct imported *out)
194f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
195f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct dir *d;
196f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t first_cluster;
197f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
198f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	DIR *dir;
199f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct dirent *de;
200f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
201f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	char ch_path[PATH_MAX];
202f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct imported *ch_imp;
203f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t ch_first_cluster;
204f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct fat_dirent *ch_dirent;
205f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
206f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
207f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
208f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *items;
209f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *item;
210f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int count;
211f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
212f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int i;
213f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
214f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	dir = opendir(path);
215f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!dir) {
216f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: opendir failed: %s\n", path, strerror(errno));
217f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
218f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
219f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
220f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d = malloc(sizeof(struct dir));
221f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!d) {
222f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't allocate dir struct: out of memory\n", path);
223f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		closedir(dir);
224f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return MALLOC_FAIL;
225f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
226f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
227f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d->path = strdup(path);
228f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!d->path) {
229f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't strdup path: out of memory\n", path);
230f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		closedir(dir);
231f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free(d);
232f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return MALLOC_FAIL;
233f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
234f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
235f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	items = NULL;
236f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	item = NULL;
237f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	count = 0;
238f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
239f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	while ((de = readdir(dir))) {
240f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (de->d_name[0] == '.') {
241f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto skip_item;
242f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
243f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
244f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ret = snprintf(ch_path, PATH_MAX, "%s/%s", path, de->d_name);
245f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (ret < 0 || ret >= PATH_MAX) {
246f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto skip_item;
247f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
248f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
249f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = alloc_item();
250f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (!item) {
251f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			WARN("importing %s: couldn't allocate item struct: out of memory\n", path);
252f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			ret = MALLOC_FAIL;
253f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto free_items;
254f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
255f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
256f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (convert_name(item->name, de->d_name)) {
257f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto skip_item;
258f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
259f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
260f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		switch (de->d_type) {
261f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			case DT_REG:
262f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				import_file(fs, ch_path, &item->imp);
263f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				item->is_dir = 0;
264f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				break;
265f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			case DT_DIR:
266f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				import_dir(fs, ch_path, 0, &item->imp);
267f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				item->is_dir = 1;
268f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				break;
269f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			default:
270f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				goto skip_item;
271f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
272f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
273f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item->next = items;
274f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		items = item;
275f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
276f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		count++;
277f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
278f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = NULL;
279f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
280f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		continue;
281f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
282f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleskip_item:
283f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (item)
284f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			free_item(item);
285f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
286f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
287f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	closedir(dir);
288f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
289f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d->size = sizeof(struct fat_dirent) * (count + (is_root ? 0 : 2));
290f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = fs_alloc_extent(fs, &d->extent, d->size, EXTENT_TYPE_DIR, &d->first_cluster);
291f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret) {
292f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't allocate directory table extent: out of space\n", path);
293f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto free_items;
294f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
295f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
296f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	first_cluster = is_root ? 0 : d->first_cluster;
297f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
298f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d->entries = malloc(sizeof(struct fat_dirent) * (count + (is_root ? 0 : 2)));
299f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(d->entries);
300f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = count - 1; i >= 0; i--) {
301f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = items;
302f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		items = item->next;
303f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
304f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ch_dirent = &d->entries[i + (is_root ? 0 : 2)];
305f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
306f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fat_dirent_set(ch_dirent,
307f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               item->name, item->is_dir ? FAT_ATTR_SUBDIR : 0,
308f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               item->imp.first_cluster, item->imp.size);
309f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
310f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (item->imp.dot_dot_dirent) {
311f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			fat_dirent_set_first_cluster(item->imp.dot_dot_dirent, first_cluster);
312f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
313f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
314f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free_item(item);
315f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
316f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
317f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!is_root) {
318f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fat_dirent_set(&d->entries[0],
319f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               "..         ", FAT_ATTR_SUBDIR,
320f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               (cluster_t)-1, 0);
321f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		out->dot_dot_dirent = &d->entries[0]; /* will set first_cluster */
322f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
323f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fat_dirent_set(&d->entries[1],
324f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               ".          ", FAT_ATTR_SUBDIR,
325f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               first_cluster, 0);
326f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	} else {
327f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		out->dot_dot_dirent = NULL;
328f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
329f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
330f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	out->first_cluster = d->first_cluster;
331f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	out->size = 0;
332f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
333f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
334f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
335f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlefree_items:
336f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free_items(items);
337f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free(d->path);
338f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free(d);
339f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
340f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return ret;
341f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
342f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
343f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleint import_tree(struct fs *fs, char *path)
344f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
345f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct imported imp;
346f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
347f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
348f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = import_dir(fs, path, 0, &imp);
349f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret)
350f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return ret;
351f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
352f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_set_rootdir_start(fs, imp.first_cluster);
353f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_update_free_clusters(fs);
354f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
355f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
356f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
357