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 |