]> git.sesse.net Git - vlc/blob - src/posix/dirs.c
Inline config_GetDataDir()
[vlc] / src / posix / dirs.c
1 /*****************************************************************************
2  * dirs.c: XDG directories configuration
3  *****************************************************************************
4  * Copyright (C) 2001-2007 VLC authors and VideoLAN
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 it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * 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 "config/configuration.h"
32
33 #include <unistd.h>
34 #include <pwd.h>
35 #include <assert.h>
36 #include <limits.h>
37
38 #if !defined (__linux__)
39 /**
40  * Determines the shared data directory
41  *
42  * @return a nul-terminated string or NULL. Use free() to release it.
43  */
44 char *config_GetDataDir (void)
45 {
46     const char *path = getenv ("VLC_DATA_PATH");
47     return strdup ((path != NULL) ? path : PKGDATADIR);
48 }
49
50 /**
51  * Determines the architecture-dependent data directory
52  *
53  * @return a string (always succeeds).
54  */
55 char *config_GetLibDir (void)
56 {
57     return strdup (PKGLIBDIR);
58 }
59 #endif
60
61 /**
62  * Determines the system configuration directory.
63  *
64  * @return a string (always succeeds).
65  */
66 const char *config_GetConfDir( void )
67 {
68     return SYSCONFDIR;
69 }
70
71 static char *config_GetHomeDir (void)
72 {
73     /* 1/ Try $HOME  */
74     const char *home = getenv ("HOME");
75 #if defined(HAVE_GETPWUID_R)
76     /* 2/ Try /etc/passwd */
77     char buf[sysconf (_SC_GETPW_R_SIZE_MAX)];
78     if (home == NULL)
79     {
80         struct passwd pw, *res;
81
82         if (!getpwuid_r (getuid (), &pw, buf, sizeof (buf), &res) && res)
83             home = pw.pw_dir;
84     }
85 #endif
86
87     if (!home)
88         return NULL;
89
90     return strdup (home);
91 }
92
93 static char *config_GetAppDir (const char *xdg_name, const char *xdg_default)
94 {
95     char *psz_dir;
96     char var[sizeof ("XDG__HOME") + strlen (xdg_name)];
97
98     /* XDG Base Directory Specification - Version 0.6 */
99     snprintf (var, sizeof (var), "XDG_%s_HOME", xdg_name);
100
101     const char *home = getenv (var);
102     if (home != NULL)
103     {
104         if (asprintf (&psz_dir, "%s/vlc", home) == -1)
105             psz_dir = NULL;
106         return psz_dir;
107     }
108
109     char *psz_home = config_GetHomeDir ();
110     if( psz_home == NULL
111      || asprintf( &psz_dir, "%s/%s/vlc", psz_home, xdg_default ) == -1 )
112         psz_dir = NULL;
113     free (psz_home);
114     return psz_dir;
115 }
116
117 static char *config_GetTypeDir (const char *xdg_name)
118 {
119     const size_t namelen = strlen (xdg_name);
120     const char *home = getenv ("HOME");
121     const char *dir = getenv ("XDG_CONFIG_HOME");
122     const char *file = "user-dirs.dirs";
123
124     if (home == NULL)
125         return NULL;
126     if (dir == NULL)
127     {
128         dir = home;
129         file = ".config/user-dirs.dirs";
130     }
131
132     char *path;
133     if (asprintf (&path, "%s/%s", dir, file) == -1)
134         return NULL;
135
136     FILE *stream = fopen (path, "rt");
137     free (path);
138     path = NULL;
139     if (stream != NULL)
140     {
141         char *linebuf = NULL;
142         size_t linelen = 0;
143
144         while (getline (&linebuf, &linelen, stream) != -1)
145         {
146             char *ptr = linebuf;
147             ptr += strspn (ptr, " \t"); /* Skip whites */
148             if (strncmp (ptr, "XDG_", 4))
149                 continue;
150             ptr += 4; /* Skip XDG_ */
151             if (strncmp (ptr, xdg_name, namelen))
152                 continue;
153             ptr += namelen; /* Skip XDG type name */
154             if (strncmp (ptr, "_DIR", 4))
155                 continue;
156             ptr += 4; /* Skip _DIR */
157             ptr += strspn (ptr, " \t"); /* Skip whites */
158             if (*ptr != '=')
159                 continue;
160             ptr++; /* Skip equality sign */
161             ptr += strspn (ptr, " \t"); /* Skip whites */
162             if (*ptr != '"')
163                 continue;
164             ptr++; /* Skip quote */
165             linelen -= ptr - linebuf;
166
167             char *out;
168             if (strncmp (ptr, "$HOME", 5))
169             {
170                 path = malloc (linelen);
171                 if (path == NULL)
172                     continue;
173                 out = path;
174             }
175             else
176             {   /* Prefix with $HOME */
177                 const size_t homelen = strlen (home);
178                 ptr += 5;
179                 path = malloc (homelen + linelen - 5);
180                 if (path == NULL)
181                     continue;
182                 memcpy (path, home, homelen);
183                 out = path + homelen;
184             }
185
186             while (*ptr != '"')
187             {
188                 if (*ptr == '\\')
189                     ptr++;
190                 if (*ptr == '\0')
191                 {
192                     free (path);
193                     path = NULL;
194                     continue;
195                 }
196                 *(out++) = *(ptr++);
197             }
198             *out = '\0';
199             break;
200         }
201         free (linebuf);
202         fclose (stream);
203     }
204
205     /* Default! */
206     if (path == NULL)
207     {
208         if (strcmp (xdg_name, "DESKTOP") == 0)
209         {
210             if (asprintf (&path, "%s/Desktop", home) == -1)
211                 return NULL;
212         }
213         else
214             path = strdup (home);
215     }
216
217     return path;
218 }
219
220
221 char *config_GetUserDir (vlc_userdir_t type)
222 {
223     switch (type)
224     {
225         case VLC_HOME_DIR:
226             break;
227         case VLC_CONFIG_DIR:
228             return config_GetAppDir ("CONFIG", ".config");
229         case VLC_DATA_DIR:
230             return config_GetAppDir ("DATA", ".local/share");
231         case VLC_CACHE_DIR:
232             return config_GetAppDir ("CACHE", ".cache");
233
234         case VLC_DESKTOP_DIR:
235             return config_GetTypeDir ("DESKTOP");
236         case VLC_DOWNLOAD_DIR:
237             return config_GetTypeDir ("DOWNLOAD");
238         case VLC_TEMPLATES_DIR:
239             return config_GetTypeDir ("TEMPLATES");
240         case VLC_PUBLICSHARE_DIR:
241             return config_GetTypeDir ("PUBLICSHARE");
242         case VLC_DOCUMENTS_DIR:
243             return config_GetTypeDir ("DOCUMENTS");
244         case VLC_MUSIC_DIR:
245             return config_GetTypeDir ("MUSIC");
246         case VLC_PICTURES_DIR:
247             return config_GetTypeDir ("PICTURES");
248         case VLC_VIDEOS_DIR:
249             return config_GetTypeDir ("VIDEOS");
250     }
251     return config_GetHomeDir ();
252 }