]> git.sesse.net Git - vlc/blob - src/config/dirs_xdg.c
Split directories configuration per platform
[vlc] / src / config / dirs_xdg.c
1 /*****************************************************************************
2  * dirs_xdg.c: XDG directories configuration
3  *****************************************************************************
4  * Copyright (C) 2001-2007 the VideoLAN team
5  * Copyright © 2007-2009 Rémi Denis-Courmont
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <vlc_common.h>
29
30 #include "../libvlc.h"
31 #include <vlc_charset.h>
32
33 #include <unistd.h>
34 #include <pwd.h>
35 #include <assert.h>
36 #include <limits.h>
37
38 /**
39  * Determines the shared data directory
40  *
41  * @return a string (always succeeds).
42  */
43 const char *config_GetDataDir( void )
44 {
45     return DATA_PATH;
46 }
47
48 /**
49  * Determines the system configuration directory.
50  *
51  * @return a string (always succeeds).
52  */
53 const char *config_GetConfDir( void )
54 {
55     return SYSCONFDIR;
56 }
57
58 static char *config_GetHomeDir (void)
59 {
60     /* 1/ Try $HOME  */
61     const char *home = getenv ("HOME");
62 #if defined(HAVE_GETPWUID_R)
63     /* 2/ Try /etc/passwd */
64     char buf[sysconf (_SC_GETPW_R_SIZE_MAX)];
65     if (home == NULL)
66     {
67         struct passwd pw, *res;
68
69         if (!getpwuid_r (getuid (), &pw, buf, sizeof (buf), &res) && res)
70             home = pw.pw_dir;
71     }
72 #endif
73
74     return FromLocaleDup (home);
75 }
76
77 static char *config_GetAppDir (const char *xdg_name, const char *xdg_default)
78 {
79     char *psz_dir;
80     char var[sizeof ("XDG__HOME") + strlen (xdg_name)];
81
82     /* XDG Base Directory Specification - Version 0.6 */
83     snprintf (var, sizeof (var), "XDG_%s_HOME", xdg_name);
84
85     char *psz_home = FromLocale (getenv (var));
86     if( psz_home )
87     {
88         if( asprintf( &psz_dir, "%s/vlc", psz_home ) == -1 )
89             psz_dir = NULL;
90         LocaleFree (psz_home);
91         return psz_dir;
92     }
93
94     psz_home = config_GetHomeDir ();
95     if( psz_home == NULL
96      || asprintf( &psz_dir, "%s/%s/vlc", psz_home, xdg_default ) == -1 )
97         psz_dir = NULL;
98     free (psz_home);
99     return psz_dir;
100 }
101
102 static char *config_GetTypeDir (const char *xdg_name)
103 {
104     const size_t namelen = strlen (xdg_name);
105     const char *home = getenv ("HOME");
106     const size_t homelen = strlen (home);
107     const char *dir = getenv ("XDG_CONFIG_HOME");
108     const char *file = "user-dirs.dirs";
109
110     if (home == NULL)
111         return NULL;
112     if (dir == NULL)
113     {
114         dir = home;
115         file = ".config/user-dirs.dirs";
116     }
117
118     char *path;
119     if (asprintf (&path, "%s/%s", dir, file) == -1)
120         return NULL;
121
122     FILE *stream = fopen (path, "rt");
123     free (path);
124     if (stream == NULL)
125         return NULL;
126
127     char *linebuf = NULL;
128     size_t linelen = 0;
129
130     while (getline (&linebuf, &linelen, stream) != -1)
131     {
132         char *ptr = linebuf;
133         ptr += strspn (ptr, " \t"); /* Skip whites */
134         if (strncmp (ptr, "XDG_", 4))
135             continue;
136         ptr += 4; /* Skip XDG_ */
137         if (strncmp (ptr, xdg_name, namelen))
138             continue;
139         ptr += namelen; /* Skip XDG type name */
140         if (strncmp (ptr, "_DIR", 4))
141             continue;
142         ptr += 4; /* Skip _DIR */
143         ptr += strspn (ptr, " \t"); /* Skip whites */
144         if (*ptr != '=')
145             continue;
146         ptr++; /* Skip equality sign */
147         ptr += strspn (ptr, " \t"); /* Skip whites */
148         if (*ptr != '"')
149             continue;
150         ptr++; /* Skip quote */
151         linelen -= ptr - linebuf;
152
153         char *out;
154         if (strncmp (ptr, "$HOME", 5))
155         {
156             path = malloc (linelen);
157             if (path == NULL)
158                 continue;
159             out = path;
160         }
161         else
162         {   /* Prefix with $HOME */
163             ptr += 5;
164             path = malloc (homelen + linelen - 5);
165             if (path == NULL)
166                 continue;
167             memcpy (path, home, homelen);
168             out = path + homelen;
169         }
170
171         while (*ptr != '"')
172         {
173             if (*ptr == '\\')
174                 ptr++;
175             if (*ptr == '\0')
176                 goto skip;
177             *(out++) = *(ptr++);
178         }
179         *out = '\0';
180         goto done;
181     skip:
182         free (path);
183     }
184
185     /* Default! */
186     if (strcmp (xdg_name, "DESKTOP") == 0)
187     {
188         if (asprintf (&path, "%s/Desktop", home) == -1)
189             path = NULL;
190     }
191     else
192         path = strdup (home);
193
194 done:
195     free (linebuf);
196     char *ret = FromLocaleDup (path);
197     free (path);
198     return ret;
199 }
200
201
202 /**
203  * Get the user's VLC cache directory
204  * (used for stuff like the modules cache, the album art cache, ...)
205  */
206 char *config_GetCacheDir( void )
207 {
208     return config_GetAppDir ("CACHE", ".cache");
209 }
210
211 char *config_GetUserDir (vlc_userdir_t type)
212 {
213     switch (type)
214     {
215         case VLC_HOME_DIR:
216             return config_GetHomeDir ();
217         case VLC_CONFIG_DIR:
218             return config_GetAppDir ("CONFIG", ".config");
219         case VLC_DATA_DIR:
220             return config_GetAppDir ("DATA", ".local/share");
221         case VLC_DESKTOP_DIR:
222             return config_GetTypeDir ("DESKTOP");
223         case VLC_DOWNLOAD_DIR:
224             return config_GetTypeDir ("DOWNLOAD");
225         case VLC_TEMPLATES_DIR:
226             return config_GetTypeDir ("TEMPLATES");
227         case VLC_PUBLICSHARE_DIR:
228             return config_GetTypeDir ("PUBLICSHARE");
229         case VLC_DOCUMENTS_DIR:
230             return config_GetTypeDir ("DOCUMENTS");
231         case VLC_MUSIC_DIR:
232             return config_GetTypeDir ("MUSIC");
233         case VLC_PICTURES_DIR:
234             return config_GetTypeDir ("PICTURES");
235         case VLC_VIDEOS_DIR:
236             return config_GetTypeDir ("VIDEOS");
237     }
238     assert (0);
239 }