gimpenv.c 23.9 KB
Newer Older
Tor Lillqvist's avatar
Tor Lillqvist committed
1
/* LIBGIMP - The GIMP Library
2
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3 4
 *
 * gimpenv.c
5
 * Copyright (C) 1999 Tor Lillqvist <tml@iki.fi>
Tor Lillqvist's avatar
Tor Lillqvist committed
6
 *
7
 * This library is free software: you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 3 of the License, or (at your option) any later version.
Tor Lillqvist's avatar
Tor Lillqvist committed
11
 *
12
 * This library is distributed in the hope that it will be useful,
Tor Lillqvist's avatar
Tor Lillqvist committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Tor Lillqvist's avatar
Tor Lillqvist committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18 19
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
Tor Lillqvist's avatar
Tor Lillqvist committed
20 21 22 23
 */

#include "config.h"

Tor Lillqvist's avatar
Tor Lillqvist committed
24
#include <string.h>
Michael Natterer's avatar
Michael Natterer committed
25
#include <sys/types.h>
26

Michael Natterer's avatar
Michael Natterer committed
27 28 29 30
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

31 32 33 34
#ifdef PLATFORM_OSX
#include <AppKit/AppKit.h>
#endif

35
#include <glib-object.h>
36 37
#include <glib/gstdio.h>

38
#undef GIMP_DISABLE_DEPRECATED
39 40
#include "gimpbasetypes.h"

41
#define __GIMP_ENV_C__
Tor Lillqvist's avatar
Tor Lillqvist committed
42
#include "gimpenv.h"
43
#include "gimpversion.h"
44
#include "gimpreloc.h"
Tor Lillqvist's avatar
Tor Lillqvist committed
45

46
#ifdef G_OS_WIN32
Tor Lillqvist's avatar
Tor Lillqvist committed
47
#define STRICT
48 49
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
50 51 52 53
#include <io.h>
#ifndef S_IWUSR
# define S_IWUSR _S_IWRITE
#endif
54 55 56 57
#ifndef S_IWGRP
#define S_IWGRP (_S_IWRITE>>3)
#define S_IWOTH (_S_IWRITE>>6)
#endif
58
#ifndef S_ISDIR
59 60
# define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
# define S_ISDIR(mode)  __S_ISTYPE((mode), _S_IFDIR)
61
#endif
62 63 64 65
#define uid_t gint
#define gid_t gint
#define geteuid() 0
#define getegid() 0
66 67 68 69 70 71 72 73 74 75 76 77 78 79

/* This is a hack for Windows known directory support.
 * DATADIR (autotools-generated constant) is a type defined in objidl.h
 * so we must #undef it before including shlobj.h in order to avoid a
 * name clash. */
static const char* datadir = DATADIR;
#undef DATADIR
#include <shlobj.h>
#define DATADIR datadir
/* Constant available since Shell32.dll 4.72 */
#ifndef CSIDL_APPDATA
#define CSIDL_APPDATA 0x001a
#endif

Tor Lillqvist's avatar
Tor Lillqvist committed
80 81
#endif

82

83 84 85 86 87 88 89 90 91 92
/**
 * SECTION: gimpenv
 * @title: gimpenv
 * @short_description: Functions to access the GIMP environment.
 *
 * A set of functions to find the locations of GIMP's data directories
 * and configuration files.
 **/


93 94 95 96 97
static gchar * gimp_env_get_dir   (const gchar *gimp_env_name,
                                   const gchar *env_dir);
#ifdef G_OS_WIN32
static gchar * get_special_folder (gint         csidl);
#endif
98

99

100 101 102 103 104
const guint gimp_major_version = GIMP_MAJOR_VERSION;
const guint gimp_minor_version = GIMP_MINOR_VERSION;
const guint gimp_micro_version = GIMP_MICRO_VERSION;


105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
/**
 * gimp_env_init:
 * @plug_in: must be %TRUE if this function is called from a plug-in
 *
 * You don't need to care about this function. It is being called for
 * you automatically (by means of the MAIN() macro that every plug-in
 * runs). Calling it again will cause a fatal error.
 *
 * Since: GIMP 2.4
 */
void
gimp_env_init (gboolean plug_in)
{
  static gboolean gimp_env_initialized = FALSE;

  if (gimp_env_initialized)
    g_error ("gimp_env_init() must only be called once!");

  gimp_env_initialized = TRUE;

#ifndef G_OS_WIN32
  if (plug_in)
    {
      _gimp_reloc_init_lib (NULL);
    }
  else if (_gimp_reloc_init (NULL))
    {
      /* Set $LD_LIBRARY_PATH to ensure that plugins can be loaded. */

      const gchar *ldpath = g_getenv ("LD_LIBRARY_PATH");
      gchar       *libdir = _gimp_reloc_find_lib_dir (NULL);

      if (ldpath && *ldpath)
        {
          gchar *tmp = g_strconcat (libdir, ":", ldpath, NULL);

141
          g_setenv ("LD_LIBRARY_PATH", tmp, TRUE);
142 143

          g_free (tmp);
144
        }
145 146 147 148 149 150 151 152 153 154
      else
        {
          g_setenv ("LD_LIBRARY_PATH", libdir, TRUE);
        }

      g_free (libdir);
    }
#endif
}

Sven Neumann's avatar
Sven Neumann committed
155 156 157
/**
 * gimp_directory:
 *
158
 * Returns the user-specific GIMP settings directory. If the
159 160 161
 * environment variable GIMP2_DIRECTORY exists, it is used. If it is
 * an absolute path, it is used as is.  If it is a relative path, it
 * is taken to be a subdirectory of the home directory. If it is a
162 163
 * relative path, and no home directory can be determined, it is taken
 * to be a subdirectory of gimp_data_directory().
Sven Neumann's avatar
Sven Neumann committed
164
 *
165
 * The usual case is that no GIMP2_DIRECTORY environment variable
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
 * exists, and then we use the GIMPDIR subdirectory of the local
 * configuration directory:
 *
 * - UNIX: $XDG_CONFIG_HOME (defaults to $HOME/.config/)
 *
 * - Windows: CSIDL_APPDATA
 *
 * - OSX (UNIX exception): the Application Support Directory.
 *
 * If neither the configuration nor home directory exist,
 * g_get_user_config_dir() will return {tmp}/{user_name}/.config/ where
 * the temporary directory {tmp} and the {user_name} are determined
 * according to platform rules.
 *
 * In any case, we always return some non-empty string, whether it
 * corresponds to an existing directory or not.
Sven Neumann's avatar
Sven Neumann committed
182
 *
183 184
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
185
 * GLib, which isn't necessarily UTF-8 (on Windows it is always
186
 * UTF-8.)
Sven Neumann's avatar
Sven Neumann committed
187 188
 *
 * Returns: The user-specific GIMP settings directory.
189
 **/
190
const gchar *
Sven Neumann's avatar
Sven Neumann committed
191
gimp_directory (void)
Tor Lillqvist's avatar
Tor Lillqvist committed
192
{
193 194
  static gchar *gimp_dir          = NULL;
  static gchar *last_env_gimp_dir = NULL;
195 196

  const gchar  *env_gimp_dir;
Tor Lillqvist's avatar
Tor Lillqvist committed
197

198 199
  env_gimp_dir = g_getenv ("GIMP2_DIRECTORY");

200
  if (gimp_dir)
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    {
      gboolean gimp2_directory_changed = FALSE;

      /* We have constructed the gimp_dir already. We can return
       * gimp_dir unless some parameter gimp_dir depends on has
       * changed. For now we just check for changes to GIMP2_DIRECTORY
       */
      gimp2_directory_changed =
        (env_gimp_dir == NULL &&
         last_env_gimp_dir != NULL) ||
        (env_gimp_dir != NULL &&
         last_env_gimp_dir == NULL) ||
        (env_gimp_dir != NULL &&
         last_env_gimp_dir != NULL &&
         strcmp (env_gimp_dir, last_env_gimp_dir) != 0);

      if (! gimp2_directory_changed)
        {
          return gimp_dir;
        }
      else
        {
          /* Free the old gimp_dir and go on to update it */
          g_free (gimp_dir);
          gimp_dir = NULL;
        }
    }
Tor Lillqvist's avatar
Tor Lillqvist committed
228

229 230 231 232 233 234
  /* Remember the GIMP2_DIRECTORY to next invocation so we can check
   * if it changes
   */
  g_free (last_env_gimp_dir);
  last_env_gimp_dir = g_strdup (env_gimp_dir);

235
  if (env_gimp_dir)
Tor Lillqvist's avatar
Tor Lillqvist committed
236 237
    {
      if (g_path_is_absolute (env_gimp_dir))
238 239 240
        {
          gimp_dir = g_strdup (env_gimp_dir);
        }
Tor Lillqvist's avatar
Tor Lillqvist committed
241
      else
242
        {
243 244
          const gchar *home_dir = g_get_home_dir ();

245
          if (home_dir)
246
            gimp_dir = g_build_filename (home_dir, env_gimp_dir, NULL);
247
          else
248
            gimp_dir = g_build_filename (gimp_data_directory (), env_gimp_dir, NULL);
249
        }
Tor Lillqvist's avatar
Tor Lillqvist committed
250 251 252
    }
  else
    {
253 254 255 256 257 258 259 260
#ifdef PLATFORM_OSX

      NSAutoreleasePool *pool;
      NSArray           *path;
      NSString          *library_dir;

      pool = [[NSAutoreleasePool alloc] init];

261
      path = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory,
262 263 264
                                                  NSUserDomainMask, YES);
      library_dir = [path objectAtIndex:0];

265
      gimp_dir = g_build_filename ([library_dir UTF8String],
266
                                   GIMPDIR, GIMP_USER_VERSION, NULL);
267 268 269

      [pool drain];

270
#elif defined G_OS_WIN32
271

272
      gchar *conf_dir = get_special_folder (CSIDL_APPDATA);
273

274 275 276
      gimp_dir = g_build_filename (conf_dir,
                                   GIMPDIR, GIMP_USER_VERSION, NULL);
      g_free(conf_dir);
277

278 279 280 281 282 283 284
#else /* UNIX */

      /* g_get_user_config_dir () always returns a path as a non-null
       * and non-empty string
       */
      gimp_dir = g_build_filename (g_get_user_config_dir (),
                                   GIMPDIR, GIMP_USER_VERSION, NULL);
285 286

#endif /* PLATFORM_OSX */
Tor Lillqvist's avatar
Tor Lillqvist committed
287 288 289 290 291
    }

  return gimp_dir;
}

292 293
#ifdef G_OS_WIN32

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
/* Taken and slightly modified from glib 2.34.0 code. */
static gchar *
get_special_folder (int csidl)
{
  wchar_t      path[MAX_PATH+1];
  HRESULT      hr;
  LPITEMIDLIST pidl = NULL;
  BOOL         b;
  gchar       *retval = NULL;

  hr = SHGetFolderLocation (NULL, csidl, NULL, 0, &pidl);
  if (hr == S_OK)
    {
      b = SHGetPathFromIDListW (pidl, path);
      if (b)
        retval = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
      CoTaskMemFree (pidl);
    }

  return retval;
}

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
static HMODULE libgimpbase_dll = NULL;

/* Minimal DllMain that just stores the handle to this DLL */

BOOL WINAPI			/* Avoid silly "no previous prototype" gcc warning */
DllMain (HINSTANCE hinstDLL,
	 DWORD     fdwReason,
	 LPVOID    lpvReserved);

BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
	 DWORD     fdwReason,
	 LPVOID    lpvReserved)
{
  switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
      libgimpbase_dll = hinstDLL;
      break;
    }

  return TRUE;
}

#endif

342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
/**
 * gimp_installation_directory:
 *
 * Returns the top installation directory of GIMP. On Unix the
 * compile-time defined installation prefix is used. On Windows, the
 * installation directory as deduced from the executable's full
 * filename is used. On OSX we ask [NSBundle mainBundle] for the
 * resource path to check if GIMP is part of a relocatable bundle.
 *
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
 * GLib, which isn't necessarily UTF-8. (On Windows it always is
 * UTF-8.)
 *
 * Since: GIMP 2.8
 *
 * Returns: The toplevel installation directory of GIMP.
 **/
const gchar *
gimp_installation_directory (void)
362 363
{
  static gchar *toplevel = NULL;
364

365
  if (toplevel)
366
    return toplevel;
367

368
#ifdef G_OS_WIN32
369

370
  {
371
    /* Figure it out from the location of this DLL */
372 373 374
    gchar *filename;
    gchar *sep1, *sep2;

375
    wchar_t w_filename[MAX_PATH];
376

377
    if (GetModuleFileNameW (libgimpbase_dll, w_filename, G_N_ELEMENTS (w_filename)) == 0)
378
      g_error ("GetModuleFilenameW failed");
379

380 381 382
    filename = g_utf16_to_utf8 (w_filename, -1, NULL, NULL, NULL);
    if (filename == NULL)
      g_error ("Converting module filename to UTF-8 failed");
383

384 385 386
    /* If the DLL file name is of the format
     * <foobar>\bin\*.dll, use <foobar>.
     * Otherwise, use the directory where the DLL is.
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
     */

    sep1 = strrchr (filename, '\\');
    *sep1 = '\0';

    sep2 = strrchr (filename, '\\');
    if (sep2 != NULL)
      {
        if (g_ascii_strcasecmp (sep2 + 1, "bin") == 0)
          {
            *sep2 = '\0';
          }
      }

    toplevel = filename;
  }
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457

#elif PLATFORM_OSX

  {
    NSAutoreleasePool *pool;
    NSString          *resource_path;
    gchar             *basename;
    gchar             *dirname;

    pool = [[NSAutoreleasePool alloc] init];

    resource_path = [[NSBundle mainBundle] resourcePath];

    basename = g_path_get_basename ([resource_path UTF8String]);
    dirname  = g_path_get_dirname ([resource_path UTF8String]);

    if (! strcmp (basename, ".libs"))
      {
        /*  we are running from the source dir, do normal unix things  */

        toplevel = _gimp_reloc_find_prefix (PREFIX);
      }
    else if (! strcmp (basename, "bin"))
      {
        /*  we are running the main app, but not from a bundle, the resource
         *  path is the directory which contains the executable
         */

        toplevel = g_strdup (dirname);
      }
    else if (! strcmp (basename, "plug-ins"))
      {
        /*  same for plug-ins, go three levels up from prefix/lib/gimp/x.y  */

        gchar *tmp  = g_path_get_dirname (dirname);
        gchar *tmp2 = g_path_get_dirname (tmp);

        toplevel = g_path_get_dirname (tmp2);

        g_free (tmp);
        g_free (tmp2);
      }
    else
      {
        /*  if none of the above match, we assume that we are really in a bundle  */

        toplevel = g_strdup ([resource_path UTF8String]);
      }

    g_free (basename);
    g_free (dirname);

    [pool drain];
  }

458
#else
459

460
  toplevel = _gimp_reloc_find_prefix (PREFIX);
461

462
#endif
463 464

  return toplevel;
465
}
466

Sven Neumann's avatar
Sven Neumann committed
467 468 469
/**
 * gimp_data_directory:
 *
470 471 472
 * Returns the top directory for GIMP data. If the environment
 * variable GIMP2_DATADIR exists, that is used.  It should be an
 * absolute pathname.  Otherwise, on Unix the compile-time defined
473 474
 * directory is used. On Windows, the installation directory as deduced
 * from the executable's full filename is used.
Sven Neumann's avatar
Sven Neumann committed
475
 *
476 477
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
478 479
 * GLib, which isn't necessarily UTF-8. (On Windows it always is
 * UTF-8.)
Sven Neumann's avatar
Sven Neumann committed
480 481
 *
 * Returns: The top directory for GIMP data.
482
 **/
483
const gchar *
Sven Neumann's avatar
Sven Neumann committed
484
gimp_data_directory (void)
Tor Lillqvist's avatar
Tor Lillqvist committed
485
{
Sven Neumann's avatar
Sven Neumann committed
486
  static gchar *gimp_data_dir = NULL;
487

488
  if (! gimp_data_dir)
489 490 491 492 493 494
    {
      gchar *tmp = _gimp_reloc_find_data_dir (DATADIR);

      gimp_data_dir = gimp_env_get_dir ("GIMP2_DATADIR", tmp);
      g_free (tmp);
    }
Tor Lillqvist's avatar
Tor Lillqvist committed
495 496 497 498

  return gimp_data_dir;
}

499 500 501 502
/**
 * gimp_locale_directory:
 *
 * Returns the top directory for GIMP locale files. If the environment
503
 * variable GIMP2_LOCALEDIR exists, that is used.  It should be an
504
 * absolute pathname.  Otherwise, on Unix the compile-time defined
505 506
 * directory is used. On Windows, the installation directory as deduced
 * from the executable's full filename is used.
507
 *
508 509
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
510 511 512 513 514
 * the C library, which isn't necessarily UTF-8. (On Windows, unlike
 * the other similar functions here, the return value from this
 * function is in the system codepage, never in UTF-8. It can thus be
 * passed directly to the bindtextdomain() function from libintl which
 * does not handle UTF-8.)
515 516 517 518 519 520 521 522
 *
 * Returns: The top directory for GIMP locale files.
 */
const gchar *
gimp_locale_directory (void)
{
  static gchar *gimp_locale_dir = NULL;

523
  if (! gimp_locale_dir)
524 525 526 527 528
    {
      gchar *tmp = _gimp_reloc_find_locale_dir (LOCALEDIR);

      gimp_locale_dir = gimp_env_get_dir ("GIMP2_LOCALEDIR", tmp);
      g_free (tmp);
529
#ifdef G_OS_WIN32
530
      tmp = g_win32_locale_filename_from_utf8 (gimp_locale_dir);
531 532 533
      g_free (gimp_locale_dir);
      gimp_locale_dir = tmp;
#endif
534
    }
535 536 537 538

  return gimp_locale_dir;
}

539 540 541 542
/**
 * gimp_sysconf_directory:
 *
 * Returns the top directory for GIMP config files. If the environment
543
 * variable GIMP2_SYSCONFDIR exists, that is used.  It should be an
544
 * absolute pathname.  Otherwise, on Unix the compile-time defined
545 546
 * directory is used. On Windows, the installation directory as deduced
 * from the executable's full filename is used.
547
 *
548 549
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
550 551
 * GLib, which isn't necessarily UTF-8. (On Windows it always is
 * UTF-8.).
552
 *
553 554
 * Returns: The top directory for GIMP config files.
 **/
555
const gchar *
556 557 558
gimp_sysconf_directory (void)
{
  static gchar *gimp_sysconf_dir = NULL;
559

560
  if (! gimp_sysconf_dir)
561 562 563 564 565 566
    {
      gchar *tmp = _gimp_reloc_find_etc_dir (SYSCONFDIR);

      gimp_sysconf_dir = gimp_env_get_dir ("GIMP2_SYSCONFDIR", tmp);
      g_free (tmp);
    }
567

568 569
  return gimp_sysconf_dir;
}
570

571 572 573 574
/**
 * gimp_user_directory:
 * @type: the type of user directory to retrieve
 *
575
 * This procedure is deprecated! Use g_get_user_special_dir() instead.
576
 *
577 578
 * Returns: The path to the specified user directory, or %NULL if the
 *          logical ID was not found.
579 580 581
 *
 * Since: GIMP 2.4
 **/
582
const gchar *
583 584
gimp_user_directory (GimpUserDirectory type)
{
585
  return g_get_user_special_dir (type);
586 587
}

588 589 590
/**
 * gimp_plug_in_directory:
 *
591 592 593
 * Returns the top directory for GIMP plug_ins and modules. If the
 * environment variable GIMP2_PLUGINDIR exists, that is used.  It
 * should be an absolute pathname. Otherwise, on Unix the compile-time
594 595
 * defined directory is used. On Windows, the installation directory as
 * deduced from the executable's full filename is used.
596
 *
597 598
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
599 600
 * GLib, which isn't necessarily UTF-8. (On Windows it always is
 * UTF-8.)
601 602 603 604 605 606 607
 *
 * Returns: The top directory for GIMP plug_ins and modules.
 **/
const gchar *
gimp_plug_in_directory (void)
{
  static gchar *gimp_plug_in_dir = NULL;
608

609
  if (! gimp_plug_in_dir)
610 611 612 613 614 615
    {
      gchar *tmp = _gimp_reloc_find_plugin_dir (PLUGINDIR);

      gimp_plug_in_dir = gimp_env_get_dir ("GIMP2_PLUGINDIR", tmp);
      g_free (tmp);
    }
616

617
  return gimp_plug_in_dir;
618 619
}

620 621 622 623 624 625 626
/**
 * gimp_personal_rc_file:
 * @basename: The basename of a rc_file.
 *
 * Returns the name of a file in the user-specific GIMP settings directory.
 *
 * The returned string is allocated dynamically and *SHOULD* be freed
627 628 629
 * with g_free() after use. The returned string is in the encoding
 * used for filenames by GLib, which isn't necessarily
 * UTF-8. (On Windows it always is UTF-8.)
630 631 632 633 634 635 636 637 638
 *
 * Returns: The name of a file in the user-specific GIMP settings directory.
 **/
gchar *
gimp_personal_rc_file (const gchar *basename)
{
  return g_build_filename (gimp_directory (), basename, NULL);
}

Sven Neumann's avatar
Sven Neumann committed
639 640 641
/**
 * gimp_gtkrc:
 *
642
 * Returns the name of GIMP's application-specific gtkrc file.
Tor Lillqvist's avatar
Tor Lillqvist committed
643
 *
644 645
 * The returned string is owned by GIMP and must not be modified or
 * freed. The returned string is in the encoding used for filenames by
646 647
 * GLib, which isn't necessarily UTF-8. (On Windows it always is
 * UTF-8.)
Sven Neumann's avatar
Sven Neumann committed
648
 *
649
 * Returns: The name of GIMP's application-specific gtkrc file.
650
 **/
651
const gchar *
Sven Neumann's avatar
Sven Neumann committed
652
gimp_gtkrc (void)
Tor Lillqvist's avatar
Tor Lillqvist committed
653
{
Sven Neumann's avatar
Sven Neumann committed
654
  static gchar *gimp_gtkrc_filename = NULL;
Tor Lillqvist's avatar
Tor Lillqvist committed
655

656
  if (! gimp_gtkrc_filename)
657 658 659
    gimp_gtkrc_filename = g_build_filename (gimp_data_directory (),
                                            "themes", "Default", "gtkrc",
                                            NULL);
660

Tor Lillqvist's avatar
Tor Lillqvist committed
661 662
  return gimp_gtkrc_filename;
}
Sven Neumann's avatar
Sven Neumann committed
663

664 665
/**
 * gimp_path_runtime_fix:
666 667
 * @path: A pointer to a string (allocated with g_malloc) that is
 *        (or could be) a pathname.
668 669 670 671 672 673 674 675 676
 *
 * On Windows, this function checks if the string pointed to by @path
 * starts with the compile-time prefix, and in that case, replaces the
 * prefix with the run-time one.  @path should be a pointer to a
 * dynamically allocated (with g_malloc, g_strconcat, etc) string. If
 * the replacement takes place, the original string is deallocated,
 * and *@path is replaced with a pointer to a new string with the
 * run-time prefix spliced in.
 *
677 678 679
 * On Linux, it does the same thing, but only if BinReloc support is enabled.
 * On other Unices, it does nothing because those platforms don't have a
 * way to find out where our binary is.
680
 */
681
static void
682 683 684 685 686 687 688 689 690 691 692 693
gimp_path_runtime_fix (gchar **path)
{
#if defined (G_OS_WIN32) && defined (PREFIX)
  gchar *p;

  /* Yes, I do mean forward slashes below */
  if (strncmp (*path, PREFIX "/", strlen (PREFIX "/")) == 0)
    {
      /* This is a compile-time entry. Replace the path with the
       * real one on this machine.
       */
      p = *path;
694
      *path = g_strconcat (gimp_installation_directory (),
695 696 697
                           "\\",
                           *path + strlen (PREFIX "/"),
                           NULL);
698 699 700 701 702 703 704 705 706 707
      g_free (p);
    }
  /* Replace forward slashes with backslashes, just for
   * completeness */
  p = *path;
  while ((p = strchr (p, '/')) != NULL)
    {
      *p = '\\';
      p++;
    }
708 709 710 711 712
#elif defined (G_OS_WIN32)
  /* without defineing PREFIX do something useful too */
  gchar *p = *path;
  if (!g_path_is_absolute (p))
    {
713
      *path = g_build_filename (gimp_installation_directory (), *path, NULL);
714 715
      g_free (p);
    }
716 717 718
#else
  gchar *p;

719 720
  if (strncmp (*path, PREFIX G_DIR_SEPARATOR_S,
               strlen (PREFIX G_DIR_SEPARATOR_S)) == 0)
721 722 723 724 725
    {
      /* This is a compile-time entry. Replace the path with the
       * real one on this machine.
       */
      p = *path;
726
      *path = g_build_filename (gimp_installation_directory (),
727 728
                                *path + strlen (PREFIX G_DIR_SEPARATOR_S),
                                NULL);
729 730
      g_free (p);
    }
731 732 733
#endif
}

Michael Natterer's avatar
Michael Natterer committed
734 735
/**
 * gimp_path_parse:
736 737
 * @path:         A list of directories separated by #G_SEARCHPATH_SEPARATOR.
 * @max_paths:    The maximum number of directories to return.
738
 * @check:        %TRUE if you want the directories to be checked.
739
 * @check_failed: Returns a #GList of path elements for which the
740
 *                check failed.
Michael Natterer's avatar
Michael Natterer committed
741
 *
742
 * Returns: A #GList of all directories in @path.
743
 **/
Michael Natterer's avatar
Michael Natterer committed
744
GList *
745
gimp_path_parse (const gchar  *path,
746 747 748
                 gint          max_paths,
                 gboolean      check,
                 GList       **check_failed)
Michael Natterer's avatar
Michael Natterer committed
749
{
750 751 752 753 754
  gchar    **patharray;
  GList     *list      = NULL;
  GList     *fail_list = NULL;
  gint       i;
  gboolean   exists    = TRUE;
Michael Natterer's avatar
Michael Natterer committed
755 756 757

  if (!path || !*path || max_paths < 1 || max_paths > 256)
    return NULL;
Sven Neumann's avatar
Sven Neumann committed
758

Michael Natterer's avatar
Michael Natterer committed
759 760 761 762 763
  patharray = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, max_paths);

  for (i = 0; i < max_paths; i++)
    {
      GString *dir;
Sven Neumann's avatar
Sven Neumann committed
764

765
      if (! patharray[i])
766
        break;
Michael Natterer's avatar
Michael Natterer committed
767

768
#ifndef G_OS_WIN32
Michael Natterer's avatar
Michael Natterer committed
769
      if (*patharray[i] == '~')
770
        {
771
          dir = g_string_new (g_get_home_dir ());
772 773
          g_string_append (dir, patharray[i] + 1);
        }
Michael Natterer's avatar
Michael Natterer committed
774
      else
775
#endif
776 777 778 779
        {
          gimp_path_runtime_fix (&patharray[i]);
          dir = g_string_new (patharray[i]);
        }
Michael Natterer's avatar
Michael Natterer committed
780 781

      if (check)
782
        exists = g_file_test (dir->str, G_FILE_TEST_IS_DIR);
Michael Natterer's avatar
Michael Natterer committed
783

784
      if (exists)
785
        list = g_list_prepend (list, g_strdup (dir->str));
Michael Natterer's avatar
Michael Natterer committed
786
      else if (check_failed)
787
        fail_list = g_list_prepend (fail_list, g_strdup (dir->str));
Michael Natterer's avatar
Michael Natterer committed
788

Michael Natterer's avatar
Michael Natterer committed
789
      g_string_free (dir, TRUE);
Michael Natterer's avatar
Michael Natterer committed
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
    }

  g_strfreev (patharray);

  list = g_list_reverse (list);

  if (check && check_failed)
    {
      fail_list = g_list_reverse (fail_list);
      *check_failed = fail_list;
    }

  return list;
}

/**
 * gimp_path_to_str:
 * @path: A list of directories as returned by gimp_path_parse().
 *
 * Returns: A searchpath string separated by #G_SEARCHPATH_SEPARATOR.
810
 **/
Michael Natterer's avatar
Michael Natterer committed
811 812 813
gchar *
gimp_path_to_str (GList *path)
{
814
  GString *str    = NULL;
Michael Natterer's avatar
Michael Natterer committed
815 816 817 818 819
  GList   *list;
  gchar   *retval = NULL;

  for (list = path; list; list = g_list_next (list))
    {
820
      gchar *dir = list->data;
821

Michael Natterer's avatar
Michael Natterer committed
822
      if (str)
823 824 825 826
        {
          g_string_append_c (str, G_SEARCHPATH_SEPARATOR);
          g_string_append (str, dir);
        }
Michael Natterer's avatar
Michael Natterer committed
827
      else
828 829 830
        {
          str = g_string_new (dir);
        }
Michael Natterer's avatar
Michael Natterer committed
831 832 833
    }

  if (str)
834
    retval = g_string_free (str, FALSE);
Michael Natterer's avatar
Michael Natterer committed
835 836 837 838 839 840 841 842

  return retval;
}

/**
 * gimp_path_free:
 * @path: A list of directories as returned by gimp_path_parse().
 *
843 844
 * This function frees the memory allocated for the list and the strings
 * it contains.
845
 **/
Michael Natterer's avatar
Michael Natterer committed
846 847 848
void
gimp_path_free (GList *path)
{
849
  g_list_free_full (path, (GDestroyNotify) g_free);
Michael Natterer's avatar
Michael Natterer committed
850 851 852 853 854 855
}

/**
 * gimp_path_get_user_writable_dir:
 * @path: A list of directories as returned by gimp_path_parse().
 *
856 857
 * Note that you have to g_free() the returned string.
 *
Michael Natterer's avatar
Michael Natterer committed
858
 * Returns: The first directory in @path where the user has write permission.
859
 **/
Michael Natterer's avatar
Michael Natterer committed
860 861 862
gchar *
gimp_path_get_user_writable_dir (GList *path)
{
863 864 865 866 867
  GList       *list;
  uid_t        euid;
  gid_t        egid;
  struct stat  filestat;
  gint         err;
Michael Natterer's avatar
Michael Natterer committed
868

869 870
  g_return_val_if_fail (path != NULL, NULL);

Michael Natterer's avatar
Michael Natterer committed
871 872 873 874 875
  euid = geteuid ();
  egid = getegid ();

  for (list = path; list; list = g_list_next (list))
    {
876
      gchar *dir = list->data;
877

878
      /*  check if directory exists  */
879
      err = g_stat (dir, &filestat);
Michael Natterer's avatar
Michael Natterer committed
880 881 882 883 884 885 886 887

      /*  this is tricky:
       *  if a file is e.g. owned by the current user but not user-writable,
       *  the user has no permission to write to the file regardless
       *  of his group's or other's write permissions
       */
      if (!err && S_ISDIR (filestat.st_mode) &&

888
          ((filestat.st_mode & S_IWUSR) ||
Michael Natterer's avatar
Michael Natterer committed
889

890 891
           ((filestat.st_mode & S_IWGRP) &&
            (euid != filestat.st_uid)) ||
Michael Natterer's avatar
Michael Natterer committed
892

893 894 895 896 897 898
           ((filestat.st_mode & S_IWOTH) &&
            (euid != filestat.st_uid) &&
            (egid != filestat.st_gid))))
        {
          return g_strdup (dir);
        }
Michael Natterer's avatar
Michael Natterer committed
899 900 901 902
    }

  return NULL;
}
903 904 905 906 907

static gchar *
gimp_env_get_dir (const gchar *gimp_env_name,
                  const gchar *env_dir)
{
908
  const gchar *env = g_getenv (gimp_env_name);
909 910 911 912

  if (env)
    {
      if (! g_path_is_absolute (env))
913
        g_error ("%s environment variable should be an absolute path.",
914
                 gimp_env_name);
915

916 917 918 919
      return g_strdup (env);
    }
  else
    {
920
      gchar *retval = g_strdup (env_dir);
921

922
      gimp_path_runtime_fix (&retval);
923

924
      return retval;
925 926
    }
}