| /* |
| This file is not licenced under the GPL like the rest of the code. |
| Its is under the MIT license, to encourage reuse by cut-and-paste. |
| |
| Copyright (c) 2007 Red Hat, inc |
| |
| Permission is hereby granted, free of charge, to any person |
| obtaining a copy of this software and associated documentation files |
| (the "Software"), to deal in the Software without restriction, |
| including without limitation the rights to use, copy, modify, merge, |
| publish, distribute, sublicense, and/or sell copies of the Software, |
| and to permit persons to whom the Software is furnished to do so, |
| subject to the following conditions: |
| |
| The above copyright notice and this permission notice shall be |
| included in all copies or substantial portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| SOFTWARE. |
| */ |
| |
| #include "base/third_party/xdg_user_dirs/xdg_user_dir_lookup.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "starboard/memory.h" |
| #include "starboard/types.h" |
| |
| /** |
| * xdg_user_dir_lookup_with_fallback: |
| * @type: a string specifying the type of directory |
| * @fallback: value to use if the directory isn't specified by the user |
| * @returns: a newly allocated absolute pathname |
| * |
| * Looks up a XDG user directory of the specified type. |
| * Example of types are "DESKTOP" and "DOWNLOAD". |
| * |
| * In case the user hasn't specified any directory for the specified |
| * type the value returned is @fallback. |
| * |
| * The return value is newly allocated and must be freed with |
| * SbMemoryDeallocate(). The return value is never NULL if @fallback != NULL, unless |
| * out of memory. |
| **/ |
| static char * |
| xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback) |
| { |
| FILE *file; |
| char *home_dir, *config_home, *config_file; |
| char buffer[512]; |
| char *user_dir; |
| char *p, *d; |
| int len; |
| int relative; |
| |
| home_dir = getenv ("HOME"); |
| |
| if (home_dir == NULL) |
| goto error; |
| |
| config_home = getenv ("XDG_CONFIG_HOME"); |
| if (config_home == NULL || config_home[0] == 0) |
| { |
| config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1); |
| if (config_file == NULL) |
| goto error; |
| |
| strcpy (config_file, home_dir); |
| strcat (config_file, "/.config/user-dirs.dirs"); |
| } |
| else |
| { |
| config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1); |
| if (config_file == NULL) |
| goto error; |
| |
| strcpy (config_file, config_home); |
| strcat (config_file, "/user-dirs.dirs"); |
| } |
| |
| file = fopen (config_file, "r"); |
| free (config_file); |
| if (file == NULL) |
| goto error; |
| |
| user_dir = NULL; |
| while (fgets (buffer, sizeof (buffer), file)) |
| { |
| /* Remove newline at end */ |
| len = strlen (buffer); |
| if (len > 0 && buffer[len-1] == '\n') |
| buffer[len-1] = 0; |
| |
| p = buffer; |
| while (*p == ' ' || *p == '\t') |
| p++; |
| |
| if (strncmp (p, "XDG_", 4) != 0) |
| continue; |
| p += 4; |
| if (strncmp (p, type, strlen (type)) != 0) |
| continue; |
| p += strlen (type); |
| if (strncmp (p, "_DIR", 4) != 0) |
| continue; |
| p += 4; |
| |
| while (*p == ' ' || *p == '\t') |
| p++; |
| |
| if (*p != '=') |
| continue; |
| p++; |
| |
| while (*p == ' ' || *p == '\t') |
| p++; |
| |
| if (*p != '"') |
| continue; |
| p++; |
| |
| relative = 0; |
| if (strncmp (p, "$HOME/", 6) == 0) |
| { |
| p += 6; |
| relative = 1; |
| } |
| else if (*p != '/') |
| continue; |
| |
| if (relative) |
| { |
| user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1); |
| if (user_dir == NULL) |
| goto error2; |
| |
| strcpy (user_dir, home_dir); |
| strcat (user_dir, "/"); |
| } |
| else |
| { |
| user_dir = (char*) malloc (strlen (p) + 1); |
| if (user_dir == NULL) |
| goto error2; |
| |
| *user_dir = 0; |
| } |
| |
| d = user_dir + strlen (user_dir); |
| while (*p && *p != '"') |
| { |
| if ((*p == '\\') && (*(p+1) != 0)) |
| p++; |
| *d++ = *p++; |
| } |
| *d = 0; |
| } |
| error2: |
| fclose (file); |
| |
| if (user_dir) |
| return user_dir; |
| |
| error: |
| if (fallback) |
| return strdup (fallback); |
| return NULL; |
| } |
| |
| /** |
| * xdg_user_dir_lookup: |
| * @type: a string specifying the type of directory |
| * @returns: a newly allocated absolute pathname |
| * |
| * Looks up a XDG user directory of the specified type. |
| * Example of types are "DESKTOP" and "DOWNLOAD". |
| * |
| * The return value is always != NULL (unless out of memory), |
| * and if a directory |
| * for the type is not specified by the user the default |
| * is the home directory. Except for DESKTOP which defaults |
| * to ~/Desktop. |
| * |
| * The return value is newly allocated and must be freed with |
| * SbMemoryDeallocate(). |
| **/ |
| char * |
| xdg_user_dir_lookup (const char *type) |
| { |
| char *dir, *home_dir, *user_dir; |
| |
| dir = xdg_user_dir_lookup_with_fallback (type, NULL); |
| if (dir != NULL) |
| return dir; |
| |
| home_dir = getenv ("HOME"); |
| |
| if (home_dir == NULL) |
| return strdup ("/tmp"); |
| |
| /* Special case desktop for historical compatibility */ |
| if (strcmp (type, "DESKTOP") == 0) |
| { |
| user_dir = (char*) malloc (strlen (home_dir) + strlen ("/Desktop") + 1); |
| if (user_dir == NULL) |
| return NULL; |
| |
| strcpy (user_dir, home_dir); |
| strcat (user_dir, "/Desktop"); |
| return user_dir; |
| } |
| |
| return strdup (home_dir); |
| } |
| |
| #ifdef STANDALONE_XDG_USER_DIR_LOOKUP |
| int |
| main (int argc, char *argv[]) |
| { |
| if (argc != 2) |
| { |
| fprintf (stderr, "Usage %s <dir-type>\n", argv[0]); |
| exit (1); |
| } |
| |
| printf ("%s\n", xdg_user_dir_lookup (argv[1])); |
| return 0; |
| } |
| #endif |