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
260cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle#include "fatblock.h"
27f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fat.h"
28f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fdpool.h"
29f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fs.h"
30f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "utils.h"
31f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
32f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic inline int valid_char(int c)
33f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
340cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	return (isalnum(c) ||
350cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		strchr("!#$%'()-@^_`{}~", c) ||
360cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		((c >= 128) && (c < 256)));
37f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
38f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
39f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic int convert_name(char *short_name, const char *long_name)
40f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
41f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int i;
42f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
43f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	const char *s;
44f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	const char *dot;
45f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int c;
46f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
47f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	dot = NULL;
48f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
49f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (s = long_name; *s; s++) {
50f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (*s == '.') {
51f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			if (dot) {
52f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				goto short_fail;
53f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			} else {
54f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				dot = s;
55f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			}
56f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		} else if (!valid_char(*s)) {
57f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto short_fail;
58f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
59f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
60f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
61f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (dot - long_name > 8) {
62f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto short_fail;
63f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
64f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
65f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (dot && (s - (dot + 1) > 3)) {
66f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto short_fail;
67f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
68f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
69f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	memset(short_name, ' ', 11);
70f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
71f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!dot) {
72f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		dot = s;
73f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
74f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
75f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = 0; i < dot - long_name; i++) {
76f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		short_name[i] = toupper(long_name[i]);
77f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
78f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
79f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = 0; i < s - dot; i++) {
80f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		short_name[8 + i] = toupper(dot[1 + i]);
81f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
82f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
83f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
84f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
85f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleshort_fail:
86f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 1;
87f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
88f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
89f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestruct imported {
90f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t first_cluster;
91f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	uint32_t size;
92f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct fat_dirent *dot_dot_dirent;
93f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle};
94f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
95f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic int import_file(struct fs *fs, char *path, struct imported *out)
96f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
97f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct stat st;
98f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct file *f = NULL;
99f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	char *path_copy = NULL;
100f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
101f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
102f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = stat(path, &st);
103f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret < 0) {
104f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: stat failed: %s\n", path, strerror(errno));
105f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
106f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
107f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
108f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f = malloc(sizeof(struct file));
109f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!f) {
1100cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("importing %s: couldn't allocate file struct: "
1110cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     "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) {
1180cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("importing %s: couldn't strdup path: out of memory\n",
1190cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     path);
120f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ret = MALLOC_FAIL;
121f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
122f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
123f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
124f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->path = path_copy;
125f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->size = st.st_size;
126f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->dev = st.st_dev;
127f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->ino = st.st_ino;
128f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	f->mtime = st.st_mtime;
129f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fdpool_init(&f->pfd);
130f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
131f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = fs_alloc_extent(fs, &f->extent,
1320cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle                              f->size, EXTENT_TYPE_FILE, &out->first_cluster);
133f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret) {
134f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		WARN("importing %s: couldn't allocate data extent\n", path);
135f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto fail;
136f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
137f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
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. */
1930cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttlestatic int import_dir(struct fs *fs, char *path, int is_root,
1940cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		      struct imported *out)
195f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
196f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct dir *d;
1970cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	cluster_t my_first_cluster;
198f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
199f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	DIR *dir;
200f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct dirent *de;
201f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
202f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	char ch_path[PATH_MAX];
203f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct imported *ch_imp;
204f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	cluster_t ch_first_cluster;
205f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct fat_dirent *ch_dirent;
206f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
207f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
208f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
209f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *items;
210f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct item *item;
211f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int count;
212f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
213f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int i;
214f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
215f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	dir = opendir(path);
216f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!dir) {
2170cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("importing %s: opendir failed: %s\n", path,
2180cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     strerror(errno));
219f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return -1;
220f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
221f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
222f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d = malloc(sizeof(struct dir));
223f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!d) {
2240cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("importing %s: couldn't allocate dir struct: "
2250cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     "out of memory\n", path);
226f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		closedir(dir);
227f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return MALLOC_FAIL;
228f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
229f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
230f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d->path = strdup(path);
231f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!d->path) {
2320cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("importing %s: couldn't strdup path: out of memory\n",
2330cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     path);
234f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		closedir(dir);
235f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free(d);
236f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return MALLOC_FAIL;
237f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
238f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
239f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	items = NULL;
240f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	item = NULL;
241f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	count = 0;
242f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
243f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	while ((de = readdir(dir))) {
244f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (de->d_name[0] == '.') {
245f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto skip_item;
246f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
247f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
248f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ret = snprintf(ch_path, PATH_MAX, "%s/%s", path, de->d_name);
249f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (ret < 0 || ret >= PATH_MAX) {
250f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto skip_item;
251f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
252f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
253f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = alloc_item();
254f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (!item) {
2550cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle			WARN("importing %s: couldn't allocate item struct: "
2560cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle			     "out of memory\n", path);
257f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			ret = MALLOC_FAIL;
258f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto free_items;
259f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
260f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
261f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (convert_name(item->name, de->d_name)) {
262f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			goto skip_item;
263f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
264f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
265f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		switch (de->d_type) {
266f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			case DT_REG:
267f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				import_file(fs, ch_path, &item->imp);
268f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				item->is_dir = 0;
269f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				break;
270f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			case DT_DIR:
271f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				import_dir(fs, ch_path, 0, &item->imp);
272f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				item->is_dir = 1;
273f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				break;
274f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			default:
275f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle				goto skip_item;
276f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
277f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
278f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item->next = items;
279f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		items = item;
280f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
281f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		count++;
282f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
283f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = NULL;
284f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
285f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		continue;
286f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
287f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleskip_item:
288f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (item)
289f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle			free_item(item);
290f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
291f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
292f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	closedir(dir);
293f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
294f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d->size = sizeof(struct fat_dirent) * (count + (is_root ? 0 : 2));
2950cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	ret = fs_alloc_extent(fs, &d->extent, d->size, EXTENT_TYPE_DIR, &out->first_cluster);
296f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret) {
2970cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		WARN("importing %s: couldn't allocate directory table extent: "
2980cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		     "out of space\n", path);
299f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		goto free_items;
300f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
301f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
3020cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	if (is_root)
3030cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle		out->first_cluster = 0;
3040cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle
3050cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle	my_first_cluster = is_root ? 0 : out->first_cluster;
306f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
307f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	d->entries = malloc(sizeof(struct fat_dirent) * (count + (is_root ? 0 : 2)));
308f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	assert(d->entries);
309f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	for (i = count - 1; i >= 0; i--) {
310f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		item = items;
311f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		items = item->next;
312f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
313f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		ch_dirent = &d->entries[i + (is_root ? 0 : 2)];
314f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
315f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fat_dirent_set(ch_dirent,
316f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               item->name, item->is_dir ? FAT_ATTR_SUBDIR : 0,
317f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               item->imp.first_cluster, item->imp.size);
318f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
319f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		if (item->imp.dot_dot_dirent) {
3200cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle			fat_dirent_set_first_cluster(item->imp.dot_dot_dirent,
3210cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle						     my_first_cluster);
322f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		}
323f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
324f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		free_item(item);
325f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
326f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
327f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (!is_root) {
328f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fat_dirent_set(&d->entries[0],
329f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               "..         ", FAT_ATTR_SUBDIR,
330f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               (cluster_t)-1, 0);
331f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		out->dot_dot_dirent = &d->entries[0]; /* will set first_cluster */
332f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
333f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		fat_dirent_set(&d->entries[1],
334f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle                               ".          ", FAT_ATTR_SUBDIR,
3350cb61411eadd92b7202e045c1c9ec8df7fb636feThomas Tuttle                               my_first_cluster, 0);
336f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	} else {
337f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		out->dot_dot_dirent = NULL;
338f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	}
339f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
340f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	out->size = 0;
341f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
342f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
343f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
344f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlefree_items:
345f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free_items(items);
346f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free(d->path);
347f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	free(d);
348f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
349f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return ret;
350f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
351f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
352f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleint import_tree(struct fs *fs, char *path)
353f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle{
354f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	struct imported imp;
355f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	int ret;
356f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
357f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	ret = import_dir(fs, path, 0, &imp);
358f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	if (ret)
359f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle		return ret;
360f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
361f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_set_rootdir_start(fs, imp.first_cluster);
362f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	fs_update_free_clusters(fs);
363f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle
364f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle	return 0;
365f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}
366