]> git.sesse.net Git - vlc/blob - src/config/dirs_xdg.c
Add --data-path option. Access the src share directory now works from build tree.
[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_GetDataDirDefault( 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     path = NULL;
125     if (stream != 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                 {
177                     free (path);
178                     path = NULL;
179                     continue;
180                 }
181                 *(out++) = *(ptr++);
182             }
183             *out = '\0';
184             break;
185         }
186         free (linebuf);
187         fclose (stream);
188     }
189
190     /* Default! */
191     if (path == NULL)
192     {
193         if (strcmp (xdg_name, "DESKTOP") == 0)
194         {
195             if (asprintf (&path, "%s/Desktop", home) == -1)
196                 path = NULL;
197         }
198         else
199             path = strdup (home);
200     }
201
202     char *ret = FromLocaleDup (path);
203     free (path);
204     return ret;
205 }
206
207
208 char *config_GetUserDir (vlc_userdir_t type)
209 {
210     switch (type)
211     {
212         case VLC_HOME_DIR:
213             break;
214         case VLC_CONFIG_DIR:
215             return config_GetAppDir ("CONFIG", ".config");
216         case VLC_DATA_DIR:
217             return config_GetAppDir ("DATA", ".local/share");
218         case VLC_CACHE_DIR:
219             return config_GetAppDir ("CACHE", ".cache");
220
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     return config_GetHomeDir ();
239 }