[Mono-devel-list] [PATCH] GetFolderPath improvements
Todd Berman
tberman at sevenl.net
Tue Jun 15 19:56:54 EDT 2004
Why is this becoming an icall?
--Todd
Ben Maurer wrote:
> Hey guys,
>
> GetFolderPath was returning paths that are not really consistent with
> the Linux background. The attached path will make us do the following
> mappings:
>
> Desktop
> DesktopDirectory
> ~/Desktop -- Luis says that this is the default on all GNOME and
> KDE systems. That should pretty much cover us for Linux.
> Personal
> ~ -- as before
> ApplicationData
> The config directory as per fd.o's XDG spec. This defaults to
> ~/.config
> LocalApplicationData
> The data folder per XDG. Defaults to ~/.local/share
> CommonApplicationData
> /etc. Should this be /usr/share.
> System
> /etc. Maybe /bin is more correct?
> Program Files
> /usr/bin
> CommonApplicationData
> /usr/share
>
> All other folders return "". Per the MSDN docs, if a folder has not been
> created on the computer, the method should return String.Empty. Before
> we would return a semi-related folder for things.
>
> Another open issue is if we should probe for the existence of the folder
> before returning it. In the windows code, it looks like we even try to
> create the file before giving up. I would appreciate comments on this.
>
> -- Ben
>
>
>
> ------------------------------------------------------------------------
>
> Index: Environment.cs
> ===================================================================
> RCS file: /cvs/public/mcs/class/corlib/System/Environment.cs,v
> retrieving revision 1.76
> diff -u -r1.76 Environment.cs
> --- Environment.cs 11 Jun 2004 01:59:23 -0000 1.76
> +++ Environment.cs 15 Jun 2004 22:41:06 -0000
> @@ -90,6 +90,8 @@
> MyPictures = 0x27,
> CommonProgramFiles = 0x2b,
> }
> +
> + const SpecialFolder MAX_SPECIAL_FOLDER = SpecialFolder.CommonProgramFiles;
>
> // TODO: Make sure the security attributes do what I expect
>
> @@ -367,96 +369,24 @@
>
>
> [MethodImplAttribute (MethodImplOptions.InternalCall)]
> - private extern static string GetWindowsFolderPath (int folder);
> + private extern static string GetFolderPathInternal (int folder);
>
> + static string [] get_folder_path_cache;
> /// <summary>
> /// Returns the fully qualified path of the
> /// folder specified by the "folder" parameter
> /// </summary>
> public static string GetFolderPath (SpecialFolder folder)
> {
> - if ((int) Platform != 128)
> - return GetWindowsFolderPath ((int) folder);
> -
> - // we can do this in managed code for non-Windows environments
> - string path = String.Empty;
> -
> - string home = GetEnvironmentVariable ("HOME");
> -
> - // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
> - string data = GetEnvironmentVariable ("XDG_DATA_HOME");
> - if ((data == null) || (data == String.Empty)) {
> - data = Path.Combine (home, ".local");
> - data = Path.Combine (data, "share");
> - }
> -
> - string config = GetEnvironmentVariable ("XDG_CONFIG_HOME");
> - if ((config == null) || (config == String.Empty)) {
> - config = Path.Combine (home, ".config");
> - }
> -
> - string cache = GetEnvironmentVariable ("XDG_CACHE_HOME");
> - if ((cache == null) || (cache == String.Empty)) {
> - cache = Path.Combine (home, ".cache");
> + if (get_folder_path_cache != null) {
> + string s = get_folder_path_cache [(int) folder];
> + if (s != null)
> + return s;
> + } else {
> + get_folder_path_cache = new string [(int)MAX_SPECIAL_FOLDER + 1];
> }
> -
> - switch (folder) {
> -#if NET_1_1
> - case SpecialFolder.MyComputer: // MyComputer is a virtual directory
> - path = "";
> - break;
> -#endif
> -
> - case SpecialFolder.Personal:
> - path = home;
> - break;
> -
> - // data related
> - case SpecialFolder.ApplicationData:
> - case SpecialFolder.LocalApplicationData:
> - case SpecialFolder.MyMusic:
> - case SpecialFolder.MyPictures:
> - case SpecialFolder.Templates:
> - path = data;
> - break;
> -
> - // configuration related
> -#if NET_1_1
> - case SpecialFolder.Desktop:
> -#endif
> - case SpecialFolder.DesktopDirectory:
> - case SpecialFolder.Favorites:
> - case SpecialFolder.Programs:
> - case SpecialFolder.SendTo:
> - case SpecialFolder.StartMenu:
> - case SpecialFolder.Startup:
> - path = config;
> - break;
> -
> - // cache related (could disappear)
> - case SpecialFolder.Cookies:
> - case SpecialFolder.History:
> - case SpecialFolder.InternetCache:
> - case SpecialFolder.Recent:
> - path = cache;
> - break;
> -
> - // programs
> - case SpecialFolder.CommonProgramFiles:
> - case SpecialFolder.ProgramFiles:
> - case SpecialFolder.System:
> - break;
> -
> - // Directories shared by all users
> - case SpecialFolder.CommonApplicationData:
> - path = Path.GetDirectoryName (GetMachineConfigPath ());
> - break;
> -
> - default:
> - throw new ArgumentException ("Invalid SpecialFolder");
> - }
> -
> - return path;
> +
> + return get_folder_path_cache [(int) folder] = GetFolderPathInternal ((int) folder);
> }
>
> public static string[] GetLogicalDrives ()
>
>
> ------------------------------------------------------------------------
>
> ? t
> Index: icall.c
> ===================================================================
> RCS file: /cvs/public/mono/mono/metadata/icall.c,v
> retrieving revision 1.498
> diff -u -r1.498 icall.c
> --- icall.c 12 Jun 2004 11:32:35 -0000 1.498
> +++ icall.c 15 Jun 2004 22:39:30 -0000
> @@ -4443,13 +4443,38 @@
> return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
> }
>
> +typedef enum {
> + MONO_FOLDER_PATH_DESKTOP = 0x00,
> + MONO_FOLDER_PATH_MYCOMPUTER = 0x11,
> + MONO_FOLDER_PATH_PROGRAMS = 0x02,
> + MONO_FOLDER_PATH_PERSONAL = 0x05,
> + MONO_FOLDER_PATH_FAVORITES = 0x06,
> + MONO_FOLDER_PATH_STARTUP = 0x07,
> + MONO_FOLDER_PATH_RECENT = 0x08,
> + MONO_FOLDER_PATH_SENDTO = 0x09,
> + MONO_FOLDER_PATH_STARTMENU = 0x0b,
> + MONO_FOLDER_PATH_MYMUSIC = 0x0d,
> + MONO_FOLDER_PATH_DESKTOPDIRECTORY = 0x10,
> + MONO_FOLDER_PATH_TEMPLATES = 0x15,
> + MONO_FOLDER_PATH_APPLICATIONDATA = 0x1a,
> + MONO_FOLDER_PATH_LOCALAPPLICATIONDATA = 0x1c,
> + MONO_FOLDER_PATH_INTERNETCACHE = 0x20,
> + MONO_FOLDER_PATH_COOKIES = 0x21,
> + MONO_FOLDER_PATH_HISTORY = 0x22,
> + MONO_FOLDER_PATH_COMMONAPPLICATIONDATA = 0x23,
> + MONO_FOLDER_PATH_SYSTEM = 0x25,
> + MONO_FOLDER_PATH_PROGRAMFILES = 0x26,
> + MONO_FOLDER_PATH_MYPICTURES = 0x27,
> + MONO_FOLDER_PATH_COMMONPROGRAMFILES = 0x2b
> +} MonoFolderPathEnum;
> +
> static MonoString*
> -ves_icall_System_Environment_GetWindowsFolderPath (int folder)
> +ves_icall_System_Environment_GetFolderPathInternal (int folder)
> {
> -#if defined (PLATFORM_WIN32)
> - #ifndef CSIDL_FLAG_CREATE
> - #define CSIDL_FLAG_CREATE 0x8000
> - #endif
> +#ifdef PLATFORM_WIN32
> +# ifndef CSIDL_FLAG_CREATE
> +# define CSIDL_FLAG_CREATE 0x8000
> +# endif
>
> WCHAR path [MAX_PATH];
> /* Create directory if no existing */
> @@ -4460,7 +4485,81 @@
> return mono_string_new_utf16 (mono_domain_get (), path, len);
> }
> #else
> - g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
> + char* path;
> + MonoString* ret;
> + switch (folder) {
> + case MONO_FOLDER_PATH_DESKTOP:
> + case MONO_FOLDER_PATH_DESKTOPDIRECTORY:
> + path = g_strconcat (g_get_home_dir (), "/Desktop", NULL);
> + ret = mono_string_new (mono_domain_get (), path);
> + g_free (path);
> + break;
> + case MONO_FOLDER_PATH_MYCOMPUTER:
> + /* this is a virtual folder, we return "" as does MS */
> + ret = NULL;
> + break;
> + case MONO_FOLDER_PATH_PERSONAL:
> + ret = mono_string_new (mono_domain_get (), g_get_home_dir ());
> + break;
> + case MONO_FOLDER_PATH_PROGRAMS:
> + case MONO_FOLDER_PATH_FAVORITES:
> + case MONO_FOLDER_PATH_STARTUP:
> + case MONO_FOLDER_PATH_RECENT:
> + case MONO_FOLDER_PATH_SENDTO:
> + case MONO_FOLDER_PATH_STARTMENU:
> + case MONO_FOLDER_PATH_MYMUSIC:
> + case MONO_FOLDER_PATH_INTERNETCACHE:
> + case MONO_FOLDER_PATH_COOKIES:
> + case MONO_FOLDER_PATH_HISTORY:
> + case MONO_FOLDER_PATH_TEMPLATES:
> + case MONO_FOLDER_PATH_MYPICTURES:
> + /* all of these either a) dont exist on linux, or b) are not
> + * standard enough to be worth giving here
> + */
> + ret = NULL;
> + break;
> +
> + case MONO_FOLDER_PATH_APPLICATIONDATA:
> + /* use FDO's CONFIG_HOME. This data will be synced across a
> + * network like the windows counterpart.
> + */
> +
> + path = g_getenv ("XDG_CONFIG_HOME");
> + if (!path)
> + path = g_strconcat (g_get_home_dir (), "/.config", NULL);
> +
> + ret = mono_string_new (mono_domain_get (), path);
> + g_free (path);
> + break;
> + case MONO_FOLDER_PATH_LOCALAPPLICATIONDATA:
> + /* use FDO's DATA_HOME. This is *NOT* synced. */
> +
> + path = g_getenv ("XDG_DATA_HOME");
> + if (!path)
> + path = g_strconcat (g_get_home_dir (), "/.local/share", NULL);
> +
> + ret = mono_string_new (mono_domain_get (), path);
> + g_free (path);
> + break;
> + case MONO_FOLDER_PATH_COMMONAPPLICATIONDATA:
> + ret = mono_string_new (mono_domain_get (), "/etc");
> + break;
> + case MONO_FOLDER_PATH_SYSTEM:
> + ret = mono_string_new (mono_domain_get (), "/etc");
> + break;
> + case MONO_FOLDER_PATH_PROGRAMFILES:
> + ret = mono_string_new (mono_domain_get (), "/usr/bin");
> + break;
> + case MONO_FOLDER_PATH_COMMONPROGRAMFILES:
> + ret = mono_string_new (mono_domain_get (), "/usr/share");
> + break;
> + default:
> + g_assert_not_reached ();
> + }
> +
> + /* should we test that the file exists? */
> + if (ret)
> + return ret;
> #endif
> return mono_string_new (mono_domain_get (), "");
> }
> @@ -5128,10 +5227,10 @@
> {"GetCommandLineArgs", mono_runtime_get_main_args},
> {"GetEnvironmentVariable", ves_icall_System_Environment_GetEnvironmentVariable},
> {"GetEnvironmentVariableNames", ves_icall_System_Environment_GetEnvironmentVariableNames},
> + {"GetFolderPathInternal", ves_icall_System_Environment_GetFolderPathInternal},
> {"GetLogicalDrivesInternal", ves_icall_System_Environment_GetLogicalDrives },
> {"GetMachineConfigPath", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path},
> {"GetOSVersionString", ves_icall_System_Environment_GetOSVersionString},
> - {"GetWindowsFolderPath", ves_icall_System_Environment_GetWindowsFolderPath},
> {"get_ExitCode", mono_environment_exitcode_get},
> {"get_HasShutdownStarted", ves_icall_System_Environment_get_HasShutdownStarted},
> {"get_MachineName", ves_icall_System_Environment_get_MachineName},
More information about the Mono-devel-list
mailing list