U0 HomeSet(U8 *dirname) {//Change home directory. dirname = DirNameAbs(dirname); Free(blkdev.home_dir); blkdev.home_dir = SysStrNew(dirname); Free(dirname); } Bool Cd(U8 *dirname=NULL, Bool make_dirs=FALSE) {//Change directory. Optionally, make directories, too. I64 maxlen, cur_dir_clus = 0; U8 *chg_to_buf, *new_cur_dir, *buf; CDrive *drive; Bool res = TRUE; if (!dirname) dirname = "~"; else if (!*dirname) return TRUE; if (dirname[1] == ':') { if (*dirname == ':') { if (Fs->cur_dv != Letter2Drive(':') && !Drive(*dirname)) return FALSE; } else if (Fs->cur_dv != Letter2Drive(*dirname) && !Drive(*dirname)) return FALSE; dirname += 2; } if (*dirname == '/' || !*dirname || !Fs->cur_dir) { Free(Fs->cur_dir); Fs->cur_dir = StrNew("/"); if (*dirname == '/') dirname++; } chg_to_buf = MStrUtil(dirname, SUF_REM_LEADING | SUF_REM_TRAILING | SUF_REM_CTRL_CHARS); maxlen = StrLen(Fs->cur_dir) + 1 + StrLen(chg_to_buf) + 1; new_cur_dir = MAlloc(maxlen); buf = MAlloc(maxlen); StrCopy(new_cur_dir, Fs->cur_dir); while (*chg_to_buf && res) { StrFirstRemove(chg_to_buf, "/", buf); if (!*buf) StrCopy(new_cur_dir, "/"); else if (!StrCompare(buf, "..")) { StrLastRemove(new_cur_dir, "/"); if (!*new_cur_dir) StrCopy(new_cur_dir, "/"); } else if (!StrCompare(buf, "~")) { Free(new_cur_dir); new_cur_dir = MAlloc(StrLen(blkdev.home_dir + 2) + 1 + StrLen(chg_to_buf) + 1); StrCopy(new_cur_dir, blkdev.home_dir + 2); if (Fs->cur_dv != Letter2Drive('~') && !Drive('~')) return FALSE; } else if (StrCompare(buf, ".") && *buf) { drive = Fs->cur_dv; cur_dir_clus = Name2DirClus(drive, new_cur_dir); switch (drive->fs_type) { case FSt_REDSEA: res = RedSeaCd(buf, cur_dir_clus); break; case FSt_FAT32: res = FAT32Cd(buf, cur_dir_clus); break; default: PrintErr("File System Not Supported\n"); res = FALSE; } if (!res && make_dirs) { Free(Fs->cur_dir); Fs->cur_dir = StrNew(new_cur_dir); res = DirMake(buf); } if (res) { if (StrCompare(new_cur_dir, "/")) CatPrint(new_cur_dir, "/"); CatPrint(new_cur_dir, buf); } } } Free(Fs->cur_dir); Fs->cur_dir = StrNew(new_cur_dir); Free(buf); Free(chg_to_buf); Free(new_cur_dir); return res; } Bool IsDir(U8 *dir_name) {//Is a str a valid, existing Dir? U8 *mask = MStrPrint("%s/*", dir_name); Bool res, old_silent = Silent; CDirContext *dirc; if (dirc = DirContextNew(mask)) { DirContextDel(dirc); res = TRUE; } else res = FALSE; Free(mask); Silent(old_silent); return res; } I64 Dir(U8 *files_find_mask, Bool full) {//List directory. CDirEntry *tmpde1 = NULL, *tmpde2; U8 *st; CDateStruct ds; I64 csize = 0xFFFF, c = 0xFFFF, res = 0; tmpde1 = FilesFind(files_find_mask); if (!(st = DirCur)) PrintErr("Invalid Drive\n"); else { if (tmpde1) { Free(st); st = MAllocIdent(tmpde1->full_name); StrLastRemove(st, "/"); if (!st[2]) StrCopy(st + 2, "/"); //Find max columns tmpde2 = tmpde1; while (tmpde2) { if (tmpde2->size > csize) csize = tmpde2->size; if (tmpde2->clus > c) c = tmpde2->clus; tmpde2 = tmpde2->next; } csize = Bsr(csize) / 4 + 1; c = Bsr(c) / 4 + 1; "$MA,T=\"Directory\",LM=\"PopUpCd;Dir;\n\"$ of %s\n", st; if (full) "__DATE__ __TIME__ %*ts %*ts\n", csize, "SIZE", c, "BLK"; else "DATE_ TIME_ %*ts\n", csize, "SIZE"; while (tmpde1) { tmpde2 = tmpde1->next; res++; if (full) "%D %T %0*tX %0*tX ", tmpde1->datetime, tmpde1->datetime, csize, tmpde1->size, c, tmpde1->clus; else { Date2Struct(&ds, tmpde1->datetime + local_time_offset); "%02d/%02d %02d:%02d %0*tX ", ds.mon, ds.day_of_mon, ds.hour, ds.min, csize, tmpde1->size; } if (tmpde1->attr & RS_ATTR_DIR) PutDirLink(tmpde1->name, tmpde1->full_name); else PutFileLink(tmpde1->name, tmpde1->full_name); '\n'; DirEntryDel(tmpde1); tmpde1 = tmpde2; } } else "No matching entries\n"; Free(st); } return res; } Bool DirMake(U8 *filename, I64 entry_count=0) {//Make directory. Cd() can also make directories. //entry_count is for preallocating dir blocks, leave it zero if you like. U8 *name; CDirContext *dirc; Bool res = FALSE; if (FileFind(filename,, FUF_JUST_DIRS)) return FALSE; if (dirc = DirContextNew(filename)) { if (*dirc->mask) { if (!FileNameCheck(dirc->mask)) PrintErr("Invalid FileName: \"%s\".\n", dirc->mask); else { "Make Directory:%s\n", filename; name = MStrUtil(dirc->mask, SUF_REM_LEADING | SUF_REM_TRAILING | SUF_REM_CTRL_CHARS); switch (dirc->drive->fs_type) { case FSt_REDSEA: res = RedSeaMkDir(dirc->drive, Fs->cur_dir, name, entry_count); break; case FSt_FAT32: res = FAT32MkDir(dirc->drive, Fs->cur_dir, name, entry_count); break; default: PrintErr("File System Not Supported\n"); } Free(name); } } DirContextDel(dirc); } return res; }