OLD | NEW |
(Empty) | |
| 1 /* |
| 2 This file is not licenced under the GPL like the rest of the code. |
| 3 Its is under the MIT license, to encourage reuse by cut-and-paste. |
| 4 |
| 5 Copyright (c) 2007 Red Hat, inc |
| 6 |
| 7 Permission is hereby granted, free of charge, to any person |
| 8 obtaining a copy of this software and associated documentation files |
| 9 (the "Software"), to deal in the Software without restriction, |
| 10 including without limitation the rights to use, copy, modify, merge, |
| 11 publish, distribute, sublicense, and/or sell copies of the Software, |
| 12 and to permit persons to whom the Software is furnished to do so, |
| 13 subject to the following conditions: |
| 14 |
| 15 The above copyright notice and this permission notice shall be |
| 16 included in all copies or substantial portions of the Software. |
| 17 |
| 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 22 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 23 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 24 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 25 SOFTWARE. |
| 26 */ |
| 27 |
| 28 #include <stdio.h> |
| 29 #include <stdlib.h> |
| 30 #include <string.h> |
| 31 |
| 32 /** |
| 33 * xdg_user_dir_lookup_with_fallback: |
| 34 * @type: a string specifying the type of directory |
| 35 * @fallback: value to use if the directory isn't specified by the user |
| 36 * @returns: a newly allocated absolute pathname |
| 37 * |
| 38 * Looks up a XDG user directory of the specified type. |
| 39 * Example of types are "DESKTOP" and "DOWNLOAD". |
| 40 * |
| 41 * In case the user hasn't specified any directory for the specified |
| 42 * type the value returned is @fallback. |
| 43 * |
| 44 * The return value is newly allocated and must be freed with |
| 45 * free(). The return value is never NULL if @fallback != NULL, unless |
| 46 * out of memory. |
| 47 **/ |
| 48 static char * |
| 49 xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback) |
| 50 { |
| 51 FILE *file; |
| 52 char *home_dir, *config_home, *config_file; |
| 53 char buffer[512]; |
| 54 char *user_dir; |
| 55 char *p, *d; |
| 56 int len; |
| 57 int relative; |
| 58 |
| 59 home_dir = getenv ("HOME"); |
| 60 |
| 61 if (home_dir == NULL) |
| 62 goto error; |
| 63 |
| 64 config_home = getenv ("XDG_CONFIG_HOME"); |
| 65 if (config_home == NULL || config_home[0] == 0) |
| 66 { |
| 67 config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-d
irs.dirs") + 1); |
| 68 if (config_file == NULL) |
| 69 goto error; |
| 70 |
| 71 strcpy (config_file, home_dir); |
| 72 strcat (config_file, "/.config/user-dirs.dirs"); |
| 73 } |
| 74 else |
| 75 { |
| 76 config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.d
irs") + 1); |
| 77 if (config_file == NULL) |
| 78 goto error; |
| 79 |
| 80 strcpy (config_file, config_home); |
| 81 strcat (config_file, "/user-dirs.dirs"); |
| 82 } |
| 83 |
| 84 file = fopen (config_file, "r"); |
| 85 free (config_file); |
| 86 if (file == NULL) |
| 87 goto error; |
| 88 |
| 89 user_dir = NULL; |
| 90 while (fgets (buffer, sizeof (buffer), file)) |
| 91 { |
| 92 /* Remove newline at end */ |
| 93 len = strlen (buffer); |
| 94 if (len > 0 && buffer[len-1] == '\n') |
| 95 buffer[len-1] = 0; |
| 96 |
| 97 p = buffer; |
| 98 while (*p == ' ' || *p == '\t') |
| 99 p++; |
| 100 |
| 101 if (strncmp (p, "XDG_", 4) != 0) |
| 102 continue; |
| 103 p += 4; |
| 104 if (strncmp (p, type, strlen (type)) != 0) |
| 105 continue; |
| 106 p += strlen (type); |
| 107 if (strncmp (p, "_DIR", 4) != 0) |
| 108 continue; |
| 109 p += 4; |
| 110 |
| 111 while (*p == ' ' || *p == '\t') |
| 112 p++; |
| 113 |
| 114 if (*p != '=') |
| 115 continue; |
| 116 p++; |
| 117 |
| 118 while (*p == ' ' || *p == '\t') |
| 119 p++; |
| 120 |
| 121 if (*p != '"') |
| 122 continue; |
| 123 p++; |
| 124 |
| 125 relative = 0; |
| 126 if (strncmp (p, "$HOME/", 6) == 0) |
| 127 { |
| 128 p += 6; |
| 129 relative = 1; |
| 130 } |
| 131 else if (*p != '/') |
| 132 continue; |
| 133 |
| 134 if (relative) |
| 135 { |
| 136 user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1); |
| 137 if (user_dir == NULL) |
| 138 goto error2; |
| 139 |
| 140 strcpy (user_dir, home_dir); |
| 141 strcat (user_dir, "/"); |
| 142 } |
| 143 else |
| 144 { |
| 145 user_dir = (char*) malloc (strlen (p) + 1); |
| 146 if (user_dir == NULL) |
| 147 goto error2; |
| 148 |
| 149 *user_dir = 0; |
| 150 } |
| 151 |
| 152 d = user_dir + strlen (user_dir); |
| 153 while (*p && *p != '"') |
| 154 { |
| 155 if ((*p == '\\') && (*(p+1) != 0)) |
| 156 p++; |
| 157 *d++ = *p++; |
| 158 } |
| 159 *d = 0; |
| 160 } |
| 161 error2: |
| 162 fclose (file); |
| 163 |
| 164 if (user_dir) |
| 165 return user_dir; |
| 166 |
| 167 error: |
| 168 if (fallback) |
| 169 return strdup (fallback); |
| 170 return NULL; |
| 171 } |
| 172 |
| 173 /** |
| 174 * xdg_user_dir_lookup: |
| 175 * @type: a string specifying the type of directory |
| 176 * @returns: a newly allocated absolute pathname |
| 177 * |
| 178 * Looks up a XDG user directory of the specified type. |
| 179 * Example of types are "DESKTOP" and "DOWNLOAD". |
| 180 * |
| 181 * The return value is always != NULL (unless out of memory), |
| 182 * and if a directory |
| 183 * for the type is not specified by the user the default |
| 184 * is the home directory. Except for DESKTOP which defaults |
| 185 * to ~/Desktop. |
| 186 * |
| 187 * The return value is newly allocated and must be freed with |
| 188 * free(). |
| 189 **/ |
| 190 char * |
| 191 xdg_user_dir_lookup (const char *type) |
| 192 { |
| 193 char *dir, *home_dir, *user_dir; |
| 194 |
| 195 dir = xdg_user_dir_lookup_with_fallback (type, NULL); |
| 196 if (dir != NULL) |
| 197 return dir; |
| 198 |
| 199 home_dir = getenv ("HOME"); |
| 200 |
| 201 if (home_dir == NULL) |
| 202 return strdup ("/tmp"); |
| 203 |
| 204 /* Special case desktop for historical compatibility */ |
| 205 if (strcmp (type, "DESKTOP") == 0) |
| 206 { |
| 207 user_dir = (char*) malloc (strlen (home_dir) + strlen ("/Desktop") + 1); |
| 208 if (user_dir == NULL) |
| 209 return NULL; |
| 210 |
| 211 strcpy (user_dir, home_dir); |
| 212 strcat (user_dir, "/Desktop"); |
| 213 return user_dir; |
| 214 } |
| 215 |
| 216 return strdup (home_dir); |
| 217 } |
| 218 |
| 219 #ifdef STANDALONE_XDG_USER_DIR_LOOKUP |
| 220 int |
| 221 main (int argc, char *argv[]) |
| 222 { |
| 223 if (argc != 2) |
| 224 { |
| 225 fprintf (stderr, "Usage %s <dir-type>\n", argv[0]); |
| 226 exit (1); |
| 227 } |
| 228 |
| 229 printf ("%s\n", xdg_user_dir_lookup (argv[1])); |
| 230 return 0; |
| 231 } |
| 232 #endif |
OLD | NEW |