2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
32 static inline int valid_char(int c)
35 strchr("!#$%'()-@^_`{}~", c) ||
36 ((c >= 128) && (c < 256)));
39 static int convert_name(char *short_name, const char *long_name)
49 for (s = long_name; *s; s++) {
56 } else if (!valid_char(*s)) {
61 if (dot - long_name > 8) {
65 if (dot && (s - (dot + 1) > 3)) {
69 memset(short_name, ' ', 11);
75 for (i = 0; i < dot - long_name; i++) {
76 short_name[i] = toupper(long_name[i]);
79 for (i = 0; i < s - dot; i++) {
80 short_name[8 + i] = toupper(dot[1 + i]);
90 cluster_t first_cluster;
92 struct fat_dirent *dot_dot_dirent;
95 static int import_file(struct fs *fs, char *path, struct imported *out)
98 struct file *f = NULL;
99 char *path_copy = NULL;
102 ret = stat(path, &st);
104 WARN("importing %s: stat failed: %s\n", path, strerror(errno));
108 f = malloc(sizeof(struct file));
110 WARN("importing %s: couldn't allocate file struct: "
111 "out of memory\n", path);
116 path_copy = strdup(path);
118 WARN("importing %s: couldn't strdup path: out of memory\n",
125 f->size = st.st_size;
128 f->mtime = st.st_mtime;
129 fdpool_init(&f->pfd);
131 ret = fs_alloc_extent(fs, &f->extent,
132 f->size, EXTENT_TYPE_FILE, &out->first_cluster);
134 WARN("importing %s: couldn't allocate data extent\n", path);
139 out->dot_dot_dirent = NULL;
158 static struct item *free_items_head;
160 static struct item *alloc_item(void)
164 if (free_items_head) {
165 item = free_items_head;
166 free_items_head = item->next;
168 item = malloc(sizeof(struct item));
169 /* May return NULL if item couldn't be allocated. */
175 static void free_item(struct item *item)
177 item->next = free_items_head;
178 free_items_head = item;
181 static void free_items(struct item *head)
185 for (tail = head; tail->next; tail = tail->next);
187 tail->next = free_items_head;
188 free_items_head = head;
191 /* TODO: With some work, this can be rewritten so we don't recurse
192 * until all memory is allocated. */
193 static int import_dir(struct fs *fs, char *path, int is_root,
194 struct imported *out)
197 cluster_t my_first_cluster;
202 char ch_path[PATH_MAX];
203 struct imported *ch_imp;
204 cluster_t ch_first_cluster;
205 struct fat_dirent *ch_dirent;
217 WARN("importing %s: opendir failed: %s\n", path,
222 d = malloc(sizeof(struct dir));
224 WARN("importing %s: couldn't allocate dir struct: "
225 "out of memory\n", path);
230 d->path = strdup(path);
232 WARN("importing %s: couldn't strdup path: out of memory\n",
243 while ((de = readdir(dir))) {
244 if (de->d_name[0] == '.') {
248 ret = snprintf(ch_path, PATH_MAX, "%s/%s", path, de->d_name);
249 if (ret < 0 || ret >= PATH_MAX) {
255 WARN("importing %s: couldn't allocate item struct: "
256 "out of memory\n", path);
261 if (convert_name(item->name, de->d_name)) {
265 switch (de->d_type) {
267 import_file(fs, ch_path, &item->imp);
271 import_dir(fs, ch_path, 0, &item->imp);
294 d->size = sizeof(struct fat_dirent) * (count + (is_root ? 0 : 2));
295 ret = fs_alloc_extent(fs, &d->extent, d->size, EXTENT_TYPE_DIR, &out->first_cluster);
297 WARN("importing %s: couldn't allocate directory table extent: "
298 "out of space\n", path);
303 out->first_cluster = 0;
305 my_first_cluster = is_root ? 0 : out->first_cluster;
307 d->entries = malloc(sizeof(struct fat_dirent) * (count + (is_root ? 0 : 2)));
309 for (i = count - 1; i >= 0; i--) {
313 ch_dirent = &d->entries[i + (is_root ? 0 : 2)];
315 fat_dirent_set(ch_dirent,
316 item->name, item->is_dir ? FAT_ATTR_SUBDIR : 0,
317 item->imp.first_cluster, item->imp.size);
319 if (item->imp.dot_dot_dirent) {
320 fat_dirent_set_first_cluster(item->imp.dot_dot_dirent,
328 fat_dirent_set(&d->entries[0],
329 ".. ", FAT_ATTR_SUBDIR,
331 out->dot_dot_dirent = &d->entries[0]; /* will set first_cluster */
333 fat_dirent_set(&d->entries[1],
334 ". ", FAT_ATTR_SUBDIR,
335 my_first_cluster, 0);
337 out->dot_dot_dirent = NULL;
352 int import_tree(struct fs *fs, char *path)
357 ret = import_dir(fs, path, 0, &imp);
361 fs_set_rootdir_start(fs, imp.first_cluster);
362 fs_update_free_clusters(fs);