| 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 |