static int testfs_checkfs(struct super_block *sb, struct bitmap *i_freemap, struct bitmap *b_freemap, int inode_nr) { struct inode *in = testfs_get_inode(sb, inode_nr); int size; int size_roundup = ROUNDUP(testfs_inode_get_size(in), BLOCK_SIZE); assert((testfs_inode_get_type(in) == I_FILE) || (testfs_inode_get_type(in) == I_DIR)); /* inode processing */ bitmap_mark(i_freemap, inode_nr); if (testfs_inode_get_type(in) == I_DIR) { int offset = 0; struct dirent *d; for (; (d = testfs_next_dirent(in, &offset)); free(d)) { if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), ".") == 0) || (strcmp(D_NAME(d), "..") == 0)) continue; testfs_checkfs(sb, i_freemap, b_freemap, d->d_inode_nr); } } /* block processing */ size = testfs_check_inode(sb, b_freemap, in); assert(size == size_roundup); testfs_put_inode(in); return 0; }
/* return 0 on success. * return negative value on error. */ static int testfs_add_dirent(struct inode *dir, char *name, int inode_nr) { struct dirent *d; int p_offset = 0, offset = 0; int found = 0; int ret = 0; int len = strlen(name) + 1; fslice_name(name, len); assert(dir); assert(testfs_inode_get_type(dir) == I_DIR); assert(name); for (; ret == 0 && found == 0; free(d)) { p_offset = offset; if ((d = testfs_next_dirent(dir, &offset)) == NULL) break; if ((d->d_inode_nr >= 0) && (strcmp(D_NAME(d), name) == 0)) { ret = -EEXIST; continue; } if ((d->d_inode_nr >= 0) || (d->d_name_len != len)) continue; found = 1; } if (ret < 0) return ret; assert(found || (p_offset == testfs_inode_get_size(dir))); return testfs_write_dirent(dir, name, len, inode_nr, p_offset); }
static int testfs_pwd(struct super_block *sb, struct inode *in) { int p_inode_nr; struct inode *p_in; struct dirent *d; int ret; assert(in); assert(testfs_inode_get_nr(in) >= 0); p_inode_nr = testfs_dir_name_to_inode_nr(in, ".."); assert(p_inode_nr >= 0); if (p_inode_nr == testfs_inode_get_nr(in)) { printf("/"); return 1; } p_in = testfs_get_inode(sb, p_inode_nr); d = testfs_find_dirent(p_in, testfs_inode_get_nr(in)); assert(d); ret = testfs_pwd(sb, p_in); testfs_put_inode(p_in); printf("%s%s", ret == 1 ? "" : "/", D_NAME(d)); free(d); return 0; }
/* returns inode_nr of dirent removed. returns negative value if name is not found */ static int testfs_remove_dirent(struct super_block *sb, struct inode *dir, char *name) { struct dirent *d; int p_offset, offset = 0; int inode_nr = -1; int ret = -ENOENT; assert(dir); assert(name); if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { return -EINVAL; } for (; inode_nr == -1; free(d)) { p_offset = offset; if ((d = testfs_next_dirent(dir, &offset)) == NULL) break; //fslice_name(D_NAME(d), d->d_name_len); if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), name) != 0)) continue; /* found the dirent */ inode_nr = d->d_inode_nr; if ((ret = testfs_remove_dirent_allowed(sb, inode_nr)) < 0) continue; /* this will break out of the loop */ d->d_inode_nr = -1; ret = testfs_write_data(dir, p_offset, (char *)d, sizeof(struct dirent) + d->d_name_len); if (ret >= 0) ret = inode_nr; } return ret; }
/* allocates memory, caller should free */ struct dirent * testfs_next_dirent(struct inode *dir, int *offset) { int ret; struct dirent d, *dp; assert(dir); assert(testfs_inode_get_type(dir) == I_DIR); if (*offset >= testfs_inode_get_size(dir)) return NULL; ret = testfs_read_data(dir, *offset, (char *)&d, sizeof(struct dirent)); if (ret < 0) return NULL; assert(d.d_name_len > 0); dp = malloc(sizeof(struct dirent) + d.d_name_len); if (!dp) return NULL; *dp = d; *offset += sizeof(struct dirent); ret = testfs_read_data(dir, *offset, D_NAME(dp), d.d_name_len); if (ret < 0) { free(dp); return NULL; } *offset += d.d_name_len; return dp; }
/* returns negative value if name within dir is not empty */ static int testfs_remove_dirent_allowed(struct super_block *sb, int inode_nr) { struct inode *dir; int offset = 0; struct dirent *d; int ret = 0; dir = testfs_get_inode(sb, inode_nr); if (testfs_inode_get_type(dir) != I_DIR) goto out; for (; ret == 0 && (d = testfs_next_dirent(dir, &offset)); free(d)) { if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), ".") == 0) || (strcmp(D_NAME(d), "..") == 0)) continue; ret = -ENOTEMPTY; } out: testfs_put_inode(dir); return ret; }
static int testfs_ls(struct inode *in, int recursive) { int offset = 0; struct dirent *d; for (; (d = testfs_next_dirent(in, &offset)); free(d)) { struct inode *cin; if (d->d_inode_nr < 0) continue; cin = testfs_get_inode(testfs_inode_get_sb(in), d->d_inode_nr); printf("%s%s\n", D_NAME(d), (testfs_inode_get_type(cin) == I_DIR) ? "/":""); if (recursive && testfs_inode_get_type(cin) == I_DIR && (strcmp(D_NAME(d), ".") != 0) && (strcmp(D_NAME(d), "..") != 0)) { testfs_ls(cin, recursive); } testfs_put_inode(cin); } return 0; }
static char * nextFileFromDir(int idx,char * pathbuf,const int bufsize) { char * fname = NULL; LOCK_PLAYMUTEX(); if ((idx < totalFiles) && (idx >= 0)) { //fetch filename based on index. fname = CoolCatFilename2Path(pathbuf, bufsize, D_PATH, D_NAME(F_INDEX(idx))); fname = pathbuf; //DBGMSG("file name = [%s]", fname); } UNLOCK_PLAYMUTEX(); return fname; }
/* returns negative value if name is not found */ int testfs_dir_name_to_inode_nr(struct inode *dir, char *name) { struct dirent *d; int offset = 0; int ret = -ENOENT; assert(dir); assert(name); assert(testfs_inode_get_type(dir) == I_DIR); for (; ret < 0 && (d = testfs_next_dirent(dir, &offset)); free(d)) { if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), name) != 0)) continue; ret = d->d_inode_nr; } return ret; }
/* return 0 on success. * return negative value on error. */ static int testfs_write_dirent(struct inode *dir, char *name, int len, int inode_nr, int offset) { int ret; struct dirent *d = malloc(sizeof(struct dirent) + len); if (!d) return -ENOMEM; assert(inode_nr >= 0); d->d_name_len = len; d->d_inode_nr = inode_nr; strcpy(D_NAME(d), name); ret = testfs_write_data(dir, offset, (char *)d, sizeof(struct dirent) + len); free(d); return ret; }
// initialize directory. // arg: original directory/file name // function shall set up the following, // 1. filter the directory properly // 2. total number of playable contents: totalFiles // 3. current file index: fileIdx static void * dirInit( void * arg ) { LOCK_PLAYMUTEX(); if (CoolBlockOpenDir(dirName, &node) < 0) { WPRINT("unable to open directory."); } else { //DBGMSG("dirPlayAV = [%d]", dirPlayAV); if (dirPlayAV == DPAV_AUDIO_) { CoolFilterDirectory(&node, CoolIsAudioFile, DF_ALL); } else if (dirPlayAV == DPAV_VIDEO_) { CoolFilterDirectory(&node, CoolIsVideoFile, DF_ALL); } else if (dirPlayAV == DPAV_NOT_DETERMINED_) { #ifdef PLAY_VIDEO_FILE_ONLY CoolFilterDirectory(&node, CoolIsVideoFile, DF_ALL); dirPlayAV = DPAV_VIDEO_; #else if (0 == CoolFilterDirectory(&node, CoolIsVideoFile, DF_ALL)) { CoolFilterDirectory(&node, CoolIsAudioFile, DF_ALL); dirPlayAV = DPAV_AUDIO_; } else dirPlayAV = DPAV_VIDEO_; #endif } } // if is playing, get index of currently playback file totalFiles = node.fdnum+node.ffnum; if (playing) { int fi; char path[PATH_MAX]; fileIdx = 0; fi = totalFiles; while(fi--) { if (!strcmp(trackName,CoolCatFilename2Path(path, PATH_MAX, D_PATH, D_NAME(F_INDEX(fi))))) { //DBGMSG("fi = %d", fi); fileIdx = fi; break; } //DBGMSG("fname = [%s]", trackName); //DBGMSG("path = [%s]", path); } } // done with directory init, broadcast. DBGMSG("done with directory initialization."); dirInited = 1; UNLOCK_PLAYMUTEX(); pthread_cond_broadcast(&playdirCond); pthread_exit(NULL); }