From 67ccdc54a29dfb55452a51857c4568f7ec850759 Mon Sep 17 00:00:00 2001 From: FreeSlave Date: Sat, 2 Apr 2016 00:43:18 +0300 Subject: [PATCH] Add more paths in getRootPaths for Linux --- src/dlangui/core/files.d | 95 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/dlangui/core/files.d b/src/dlangui/core/files.d index 3924d9d2..b4b0aedb 100644 --- a/src/dlangui/core/files.d +++ b/src/dlangui/core/files.d @@ -115,6 +115,54 @@ struct RootEntry { return path; } +version(linux) +{ + import core.stdc.stdio : FILE; + struct mntent + { + char *mnt_fsname; /* Device or server for filesystem. */ + char *mnt_dir; /* Directory mounted on. */ + char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */ + char *mnt_opts; /* Comma-separated options for fs. */ + int mnt_freq; /* Dump frequency (in days). */ + int mnt_passno; /* Pass number for `fsck'. */ + }; + + extern(C) @nogc nothrow + { + FILE *setmntent(const char *file, const char *mode); + mntent *getmntent(FILE *stream); + mntent *getmntent_r(FILE * stream, mntent *result, char * buffer, int bufsize); + int addmntent(FILE* stream, const mntent *mnt); + int endmntent(FILE * stream); + char *hasmntopt(const mntent *mnt, const char *opt); + } + + string unescapeLabel(string label) + { + import std.string : replace; + return label.replace("\\x20", " ") + .replace("\\x9", " ") //actually tab + .replace("\\x5c", "\\") + .replace("\\xA", " "); //actually newline + } + + bool isSpecialFileSystem(const(char)[] dir, const(char)[] type) + { + import std.string : startsWith; + if (dir.startsWith("/dev") || dir.startsWith("/proc") || dir.startsWith("/sys") || + dir.startsWith("/var/run") || dir.startsWith("/var/lock")) + { + return true; + } + + if (type == "tmpfs" || type == "rootfs" || type == "rpc_pipefs") { + return true; + } + return false; + } +} + /// returns array of system root entries @property RootEntry[] getRootPaths() { RootEntry[] res; @@ -122,6 +170,53 @@ struct RootEntry { version (Posix) { res ~= RootEntry(RootEntryType.ROOT, "/", "File System"d); } + version(linux) { + import std.string : fromStringz; + import std.format : format; + + mntent ent; + char[1024] buf; + FILE* f = setmntent("/etc/mtab", "r"); + + if (f) { + scope(exit) endmntent(f); + while(getmntent_r(f, &ent, buf.ptr, cast(int)buf.length) !is null) { + auto fsName = fromStringz(ent.mnt_fsname); + auto mountDir = fromStringz(ent.mnt_dir); + auto type = fromStringz(ent.mnt_type); + + if (mountDir == "/" || //root is already added + isSpecialFileSystem(mountDir, type)) //don't list special file systems + { + continue; + } + + string label; + enum byLabel = "/dev/disk/by-label"; + try { + foreach(entry; dirEntries(byLabel, SpanMode.shallow)) + { + if (entry.isSymlink) { + auto normalized = buildNormalizedPath(byLabel, entry.readLink); + if (normalized == fsName) { + label = entry.name.baseName.unescapeLabel(); + } + } + } + } catch(Exception e) { + + } + + if (!label.length) { + label = format("%s volume", type); + } + + auto entryType = (type == "vfat") ? RootEntryType.REMOVABLE : RootEntryType.FIXED; //just a guess + res ~= RootEntry(entryType, mountDir.idup, label.toUTF32); + } + } + } + version (Windows) { import win32.windows; uint mask = GetLogicalDrives();