int dfs_romfs_read(struct dfs_fd *file, void *buf, size_t count) { rt_size_t length; struct romfs_dirent *dirent; dirent = (struct romfs_dirent *)file->data; RT_ASSERT(dirent != NULL); if (check_dirent(dirent) != 0) { return -EIO; } if (count < file->size - file->pos) length = count; else length = file->size - file->pos; if (length > 0) memcpy(buf, &(dirent->data[file->pos]), length); /* update file current position */ file->pos += length; return length; }
int dfs_romfs_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count) { rt_size_t index; const char *name; struct dirent *d; struct romfs_dirent *dirent, *sub_dirent; dirent = (struct romfs_dirent *)file->data; if (check_dirent(dirent) != 0) return -EIO; RT_ASSERT(dirent->type == ROMFS_DIRENT_DIR); /* enter directory */ dirent = (struct romfs_dirent *)dirent->data; /* make integer count */ count = (count / sizeof(struct dirent)); if (count == 0) return -EINVAL; index = 0; for (index = 0; index < count && file->pos < file->size; index ++) { d = dirp + index; sub_dirent = &dirent[file->pos]; name = sub_dirent->name; /* fill dirent */ if (sub_dirent->type == ROMFS_DIRENT_DIR) d->d_type = DT_DIR; else d->d_type = DT_REG; d->d_namlen = rt_strlen(name); d->d_reclen = (rt_uint16_t)sizeof(struct dirent); rt_strncpy(d->d_name, name, rt_strlen(name) + 1); /* move to next position */ ++ file->pos; } return index * sizeof(struct dirent); }
int dfs_romfs_open(struct dfs_fd *file) { rt_size_t size; struct romfs_dirent *dirent; struct romfs_dirent *root_dirent; struct dfs_filesystem *fs; fs = (struct dfs_filesystem *)file->data; root_dirent = (struct romfs_dirent *)fs->data; if (check_dirent(root_dirent) != 0) return -EIO; if (file->flags & (O_CREAT | O_WRONLY | O_APPEND | O_TRUNC | O_RDWR)) return -EINVAL; dirent = dfs_romfs_lookup(root_dirent, file->path, &size); if (dirent == NULL) return -ENOENT; /* entry is a directory file type */ if (dirent->type == ROMFS_DIRENT_DIR) { if (!(file->flags & O_DIRECTORY)) return -ENOENT; } else { /* entry is a file, but open it as a directory */ if (file->flags & O_DIRECTORY) return -ENOENT; } file->data = dirent; file->size = size; file->pos = 0; return RT_EOK; }
struct romfs_dirent *dfs_romfs_lookup(struct romfs_dirent *root_dirent, const char *path, rt_size_t *size) { rt_size_t index, found; const char *subpath, *subpath_end; struct romfs_dirent *dirent; rt_size_t dirent_size; /* Check the root_dirent. */ if (check_dirent(root_dirent) != 0) return NULL; if (path[0] == '/' && path[1] == '\0') { *size = root_dirent->size; return root_dirent; } /* goto root directy entries */ dirent = (struct romfs_dirent *)root_dirent->data; dirent_size = root_dirent->size; /* get the end position of this subpath */ subpath_end = path; /* skip /// */ while (*subpath_end && *subpath_end == '/') subpath_end ++; subpath = subpath_end; while ((*subpath_end != '/') && *subpath_end) subpath_end ++; while (dirent != NULL) { found = 0; /* search in folder */ for (index = 0; index < dirent_size; index ++) { if (check_dirent(&dirent[index]) != 0) return NULL; if (rt_strlen(dirent[index].name) == (subpath_end - subpath) && rt_strncmp(dirent[index].name, subpath, (subpath_end - subpath)) == 0) { dirent_size = dirent[index].size; /* skip /// */ while (*subpath_end && *subpath_end == '/') subpath_end ++; subpath = subpath_end; while ((*subpath_end != '/') && *subpath_end) subpath_end ++; if (!(*subpath)) { *size = dirent_size; return &dirent[index]; } if (dirent[index].type == ROMFS_DIRENT_DIR) { /* enter directory */ dirent = (struct romfs_dirent*)dirent[index].data; found = 1; break; } else { /* return file dirent */ if (subpath != NULL) break; /* not the end of path */ return &dirent[index]; } } } if (!found) break; /* not found */ } /* not found */ return NULL; }
static int catsearch(struct vol *vol, struct dir *dir, int rmatches, uint32_t *pos, char *rbuf, uint32_t *nrecs, int *rsize, int ext) { static u_int32_t cur_pos; /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */ static DIR *dirpos; /* UNIX structure describing currently opened directory. */ struct dir *currentdir; /* struct dir of current directory */ int cidx, r; struct dirent *entry; int result = AFP_OK; int ccr; struct path path; char *vpath = vol->v_path; char *rrbuf = rbuf; time_t start_time; int num_rounds = NUM_ROUNDS; int cwd = -1; int error; int unlen; if (*pos != 0 && *pos != cur_pos) { result = AFPERR_CATCHNG; goto catsearch_end; } /* FIXME: Category "offspring count ! */ /* We need to initialize all mandatory structures/variables and change working directory appropriate... */ if (*pos == 0) { clearstack(); if (dirpos != NULL) { closedir(dirpos); dirpos = NULL; } if (addstack(vpath, dir, -1) == -1) { result = AFPERR_MISC; goto catsearch_end; } /* FIXME: Sometimes DID is given by client ! (correct this one above !) */ } /* Save current path */ if ((cwd = open(".", O_RDONLY)) < 0) { result = AFPERR_MISC; goto catsearch_end; } /* So we are beginning... */ start_time = time(NULL); while ((cidx = reducestack()) != -1) { if ((currentdir = dirlookup(vol, dstack[cidx].ds_did)) == NULL) { result = AFPERR_MISC; goto catsearch_end; } LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath)); error = movecwd(vol, currentdir); if (!error && dirpos == NULL) dirpos = opendir("."); if (dirpos == NULL) dirpos = opendir(bdata(currentdir->d_fullpath)); if (error || dirpos == NULL) { switch (errno) { case EACCES: dstack[cidx].ds_checked = 1; continue; case EMFILE: case ENFILE: case ENOENT: result = AFPERR_NFILE; break; case ENOMEM: case ENOTDIR: default: result = AFPERR_MISC; } /* switch (errno) */ goto catsearch_end; } while ((entry = readdir(dirpos)) != NULL) { (*pos)++; if (!check_dirent(vol, entry->d_name)) continue; LOG(log_debug, logtype_afpd, "catsearch(\"%s\"): dirent: \"%s\"", cfrombstr(currentdir->d_fullpath), entry->d_name); memset(&path, 0, sizeof(path)); path.u_name = entry->d_name; if (of_stat(vol, &path) != 0) { switch (errno) { case EACCES: case ELOOP: case ENOENT: continue; case ENOTDIR: case EFAULT: case ENOMEM: case ENAMETOOLONG: default: result = AFPERR_MISC; goto catsearch_end; } } switch (S_IFMT & path.st.st_mode) { case S_IFDIR: /* here we can short cut ie if in the same loop the parent dir wasn't in the cache ALL dirsearch_byname will fail. */ unlen = strlen(path.u_name); path.d_dir = dircache_search_by_name(vol, currentdir, path.u_name, unlen); if (path.d_dir == NULL) { /* path.m_name is set by adddir */ if ((path.d_dir = dir_add(vol, currentdir, &path, unlen)) == NULL) { result = AFPERR_MISC; goto catsearch_end; } } path.m_name = cfrombstr(path.d_dir->d_m_name); if (addstack(path.u_name, path.d_dir, cidx) == -1) { result = AFPERR_MISC; goto catsearch_end; } break; case S_IFREG: path.d_dir = currentdir; break; default: continue; } ccr = crit_check(vol, &path); /* bit 0 means that criteria has been met */ if ((ccr & 1)) { r = rslt_add ( vol, &path, &rrbuf, ext); if (r == 0) { result = AFPERR_MISC; goto catsearch_end; } *nrecs += r; /* Number of matches limit */ if (--rmatches == 0) goto catsearch_pause; /* Block size limit */ if (rrbuf - rbuf >= 448) goto catsearch_pause; } /* MacOS 9 doesn't like servers executing commands longer than few seconds */ if (--num_rounds <= 0) { if (start_time != time(NULL)) { result=AFP_OK; goto catsearch_pause; } num_rounds = NUM_ROUNDS; } } /* while ((entry=readdir(dirpos)) != NULL) */ closedir(dirpos); dirpos = NULL; dstack[cidx].ds_checked = 1; } /* while (current_idx = reducestack()) != -1) */ /* We have finished traversing our tree. Return EOF here. */ result = AFPERR_EOF; goto catsearch_end; catsearch_pause: cur_pos = *pos; save_cidx = cidx; catsearch_end: /* Exiting catsearch: error condition */ *rsize = rrbuf - rbuf; if (cwd != -1) { if ((fchdir(cwd)) != 0) { LOG(log_debug, logtype_afpd, "error chdiring back: %s", strerror(errno)); } close(cwd); } return result; } /* catsearch() */