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