[Mono-devel-list] [PATCH] GetFolderPath improvements

Ben Maurer bmaurer at ximian.com
Tue Jun 15 20:14:25 EDT 2004


I should have explained this part, thank you for reminding me.

As I mentioned on IRC, this is so that we can use #ifdef to do specific
testing for platforms. IMHO, this is something that is cleaner if we can
use the autoconf information.

-- Ben

On Tue, 2004-06-15 at 19:56, Todd Berman wrote:
> 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