1 /*
2   Copyright 2021 Northern.tech AS
3 
4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 3.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
18 
19   To the extent this program is licensed as part of the Enterprise
20   versions of CFEngine, the applicable Commercial Open Source License
21   (COSL) may apply to this file if you as a licensee so wish it. See
22   included file COSL.txt.
23 */
24 
25 #include "../config.h"
26 #include <known_dirs.h>
27 #include <definitions.h>
28 #include <file_lib.h>
29 
30 static char OVERRIDE_BINDIR[PATH_MAX] = {0};
31 
32 #if defined(__CYGWIN__) || defined(__ANDROID__)
33 
34 #define GET_DEFAULT_DIRECTORY_DEFINE(FUNC, GLOBAL)  \
35 static const char *GetDefault##FUNC##Dir(void)      \
36 {                                                   \
37     return GLOBAL;                                  \
38 }
39 
40 /* getpwuid() on Android returns /data,
41  * so use compile-time default instead */
GET_DEFAULT_DIRECTORY_DEFINE(Work,WORKDIR)42 GET_DEFAULT_DIRECTORY_DEFINE(Work, WORKDIR)
43 GET_DEFAULT_DIRECTORY_DEFINE(Bin, BINDIR)
44 GET_DEFAULT_DIRECTORY_DEFINE(Data, CF_DATADIR)
45 GET_DEFAULT_DIRECTORY_DEFINE(Log, LOGDIR)
46 GET_DEFAULT_DIRECTORY_DEFINE(Pid, PIDDIR)
47 GET_DEFAULT_DIRECTORY_DEFINE(Input, INPUTDIR)
48 GET_DEFAULT_DIRECTORY_DEFINE(Master, MASTERDIR)
49 GET_DEFAULT_DIRECTORY_DEFINE(State, STATEDIR)
50 
51 #elif !defined(__MINGW32__)
52 
53 const char *GetDefaultDir_helper(char dir[PATH_MAX], const char *root_dir,
54                                  const char *append_dir)
55 {
56     assert(dir != NULL);
57 
58     if (getuid() > 0)
59     {
60         if (dir[0] == '\0')
61         {
62             struct passwd *mpw = getpwuid(getuid());
63 
64             if (mpw == NULL)
65             {
66                 return NULL;
67             }
68 
69             if ( append_dir == NULL )
70             {
71                 if (snprintf(dir, PATH_MAX, "%s/.cfagent",
72                              mpw->pw_dir) >= PATH_MAX)
73                 {
74                     return NULL;
75                 }
76             }
77             else
78             {
79                 if (snprintf(dir, PATH_MAX, "%s/.cfagent/%s",
80                              mpw->pw_dir, append_dir) >= PATH_MAX)
81                 {
82                     return NULL;
83                 }
84             }
85         }
86         return dir;
87     }
88     else
89     {
90         return root_dir;
91     }
92 }
93 
94 #endif
95 
96 #define GET_DEFAULT_DIRECTORY_DEFINE(FUNC, STATIC, GLOBAL, FOLDER)  \
97 const char *GetDefault##FUNC##Dir(void)                             \
98 {                                                                   \
99     static char STATIC##dir[PATH_MAX]; /* GLOBAL_C */               \
100     return GetDefaultDir_helper(STATIC##dir, GLOBAL, FOLDER);       \
101 }
102 
103 #if !defined(__CYGWIN__) && !defined(__ANDROID__)
104 GET_DEFAULT_DIRECTORY_DEFINE(Work, work, WORKDIR, NULL)
105 GET_DEFAULT_DIRECTORY_DEFINE(Bin, bin, BINDIR, "bin")
106 GET_DEFAULT_DIRECTORY_DEFINE(Data, data, CF_DATADIR, "data")
107 GET_DEFAULT_DIRECTORY_DEFINE(Log, log, LOGDIR, "log")
108 GET_DEFAULT_DIRECTORY_DEFINE(Pid, pid, PIDDIR, NULL)
109 GET_DEFAULT_DIRECTORY_DEFINE(Master, master, MASTERDIR, "masterfiles")
110 GET_DEFAULT_DIRECTORY_DEFINE(Input, input, INPUTDIR, "inputs")
111 GET_DEFAULT_DIRECTORY_DEFINE(State, state, STATEDIR, "state")
112 #endif
113 
114 
115 /*******************************************************************/
116 
117 const char *GetWorkDir(void)
118 {
119     const char *workdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR");
120 
121     return workdir == NULL ? GetDefaultWorkDir() : workdir;
122 }
123 
GetBinDir(void)124 const char *GetBinDir(void)
125 {
126     const char *workdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR");
127 
128     if (workdir == NULL)
129     {
130 #ifdef __MINGW32__
131         /* Compile-time default bindir doesn't work on windows because during
132          * the build /var/cfengine/bin is used and only when the package is
133          * created, things are shuffled around */
134         snprintf(OVERRIDE_BINDIR, PATH_MAX, "%s%cbin",
135                  GetDefaultWorkDir(), FILE_SEPARATOR);
136         return OVERRIDE_BINDIR;
137 #else
138         return GetDefaultBinDir();
139 #endif
140     }
141     else
142     {
143         snprintf(OVERRIDE_BINDIR, PATH_MAX, "%s%cbin",
144                  workdir, FILE_SEPARATOR);
145         return OVERRIDE_BINDIR;
146     }
147 }
148 
GetLogDir(void)149 const char *GetLogDir(void)
150 {
151     const char *logdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR");
152 
153     return logdir == NULL ? GetDefaultLogDir() : logdir;
154 }
155 
GetPidDir(void)156 const char *GetPidDir(void)
157 {
158     const char *piddir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR");
159 
160     return piddir == NULL ? GetDefaultPidDir() : piddir;
161 }
162 
163 #define GET_DIRECTORY_DEFINE_FUNC_BODY(FUNC, VAR, GLOBAL, FOLDER)    \
164 {                                                                    \
165     const char *VAR##dir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); \
166                                                                      \
167     static char workbuf[CF_BUFSIZE];                                 \
168                                                                      \
169     if (VAR##dir != NULL)                                            \
170     {                                                                \
171         snprintf(workbuf, CF_BUFSIZE, "%s/" #FOLDER, VAR##dir);      \
172     }                                                                \
173     else if (strcmp(GLOBAL##DIR, "default") == 0 )                   \
174     {                                                                \
175         snprintf(workbuf, CF_BUFSIZE, "%s/" #FOLDER, GetWorkDir());  \
176     }                                                                \
177     else /* VAR##dir defined at compile-time */                      \
178     {                                                                \
179         return GetDefault##FUNC##Dir();                              \
180     }                                                                \
181                                                                      \
182     return MapName(workbuf);                                         \
183 }
184 
185 const char *GetInputDir(void)
186     GET_DIRECTORY_DEFINE_FUNC_BODY(Input, input, INPUT, inputs)
187 const char *GetMasterDir(void)
188     GET_DIRECTORY_DEFINE_FUNC_BODY(Master, master, MASTER, masterfiles)
189 const char *GetStateDir(void)
190     GET_DIRECTORY_DEFINE_FUNC_BODY(State, state, STATE, state)
191 const char *GetDataDir(void)
192     GET_DIRECTORY_DEFINE_FUNC_BODY(Data, data, CF_DATA, data)
193