summaryrefslogtreecommitdiff
path: root/src/platform_adapters/linux/configfiles.cpp
blob: 8e2f36b1ab758f525616dcd6d56c7e837ecb7b1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
 *  File:         configfiles.cpp
 *
 *  Author:       Lukas Zeller (luz@synthesis.ch)
 *
 *  Linux Platform adaptor for accessing config files
 *
 *  Copyright (c) 2002-2009 by Synthesis AG (www.synthesis.ch)
 *
 *  2002-11-18 : luz : created
 *
 *
 */

#include "sysync.h"

#ifdef ANDROID
#include <unistd.h>
#endif

#include <sys/types.h>
#include <pwd.h>


// determine OS version
static bool getOSVersion(string &aOSVersion)
{
  // Obtain OS Version
  //%%%% for now
  aOSVersion="unknown";
  return false;
} // getOSVersion


// determine hardware name
static bool getHardwareName(string &aHardwareName)
{
  // Obtain Device name
  #ifdef ANDROID
  aHardwareName="Android Device";
  #else
  aHardwareName="Linux PC";
  #endif
  return true;
} // getHardwareName


/// @brief get platform specific string by ID
/// @return false if string is not available for this platform
/// @param aStringID string selector ID
/// @param aString will receive the requested string
bool getPlatformString(TPlatformStringID aStringID, string &aString)
{
  const sInt16 bufsiz=1024;
  char buffer[bufsiz];
  buffer[0]=0; // terminate for safety
  string str;
  string aSub;
  struct passwd *userInfoP=NULL;

  switch (aStringID) {
    case pfs_platformvers:
      // Platform OS version string
      getOSVersion(aString);
      break;
    case pfs_device_uri:
      getLocalDeviceID(aString);
      break;
    case pfs_device_name:
      getHardwareName(aString);
      break;
    case pfs_loccfg_path:
      #ifdef STANDALONE_APP
      // default path for local config for XPT standalones is the current dir
      aString = ".";
      break;
      #endif
      // for server modules, it is same as the global config path
    #ifndef STANDALONE_APP
    case pfs_globcfg_path:
      // global config directory path
      aString = "/etc";
      break;
    #endif
    case pfs_defout_path:
      // default output path (formerly: default write path)
      #ifdef STANDALONE_APP
      // default path for local config for XPT standalones is the current dir
      aString = ".";
      #else
      // for server modules, default log path is /var/log
      aString = "/var/log";
      #endif
      break;
    case pfs_temp_path:
      // temp path
      aString = "/temp";
      break;
    case pfs_userdir_path:
      // user's home dir for user-visible documents and files
      userInfoP = getpwuid(getuid());
      aString = userInfoP->pw_dir; // home dir
      break;
    #ifdef APPDATA_SUBDIR
    case pfs_appdata_path:
      // My specific subdirectory for storing my app data/prefs
      userInfoP = getpwuid(getuid());
      aString = userInfoP->pw_dir; // user home dir
      aSub = APPDATA_SUBDIR;
      #ifdef ANDROID
      aString += "/data/com.sysync"; // application specific subdir for android
      if (!aSub.empty()) aString+= "/"; // slash only if subdir is really there
      #else
      aString += "/.sysync/"; // application specific subdir
      // don't adapt it here to avoid potential problems on other platforms
      #endif
      aString += aSub;
      break;
    #endif
    /*
    case pfs_prefs_path:
      // general directory where all applications store data & prefs (for current user)
      aString = %%%
      break;
    */
    /*
    case pfs_exedir_path:
    exedir:
      // path where module file resides
      aString = %%%
      break;
    */
    default:
      // unknown ID
      return false;
  }
  // ok
  return true;
} // getPlatformString


extern "C" {
  #ifndef ANDROID
  #include <ctime>
  #endif

  #include <sys/stat.h>
}

/// @brief update string such that it can be used as target OS directory path
///   (filename can be appended without any separator)
/// @param aPath path to be updated
/// @param aMakeDirs if set, directories along path are created if not existing
/// @return false if directory does not exist or could not be created (when aMakeDirs is set)
bool makeOSDirPath(string &aPath, bool aMakeDirs)
{
  // make sure path ends with backslash
  string::size_type n=aPath.size();
  if (n>=1 && aPath[n-1]!='/')
    aPath+='/';
  // now make sure path exists if requested
  if (aMakeDirs) {
    // no slash at the end
    string tmppath;
    tmppath.assign(aPath,0,aPath.size()-1);
    // optimization check if entire path exists
    struct stat statinfo;
    int rc=stat(aPath.c_str(),&statinfo);
    if(rc!=0 || !S_ISDIR(statinfo.st_mode)) {
      #ifdef ANDROID
      rc = 0; // BFO_INCOMPLETE
      #else
      rc = errno;
      #endif
      // path does not exist yet - start from beginning to create it
      n=0;
      bool knownmissing=false;
      // skip first slash for absolute paths
      if (aPath[0]=='/') n+=1; // skip
      do {
        // find first directory in path
        n=aPath.find("/",n);
        // if no more separators to find, all dirs exist now
        if (n==string::npos) break;
        tmppath.assign(aPath,0,n);
        n+=1; // skip separator
        if (!knownmissing) {
          // test if this dir exists
          rc=stat(tmppath.c_str(),&statinfo);
          if(rc!=0 || !S_ISDIR(statinfo.st_mode)) {
            #ifdef ANDROID
            rc = 0; // BFO_INCOMPLETE
            #else
            rc = errno;
            #endif
            knownmissing=true;
          }
        }
        if (knownmissing) {
          // create the subdir (might fail if part of path already exists)
          if (mkdir(tmppath.c_str(),S_IRWXU)!=0)
            return false; // failure to create directory
        }
      } while(true);
    } // path does not exist yet entirely
  } // make path existing
  return true;
} // makeOSDirPath


// returns timestamp (UTC) of last file modification or 0 if none known
lineartime_t getFileModificationDate(const char *aFileName)
{
  struct stat st;
  lineartime_t res;

  if (stat(aFileName,&st)!=0) res=0;
  else {
    // stat ok, get modification date
    res= ((lineartime_t)st.st_mtime * secondToLinearTimeFactor) + UnixToLineartimeOffset;
  }
  // return timestamp
  return res;
} // getFileModificationDate


#include <netdb.h>
#include <unistd.h>

// get local device URI/name info
bool getLocalDeviceID(string &aURI)
{
  char     szHostname[100];
  struct hostent *pHostEnt=NULL;
  string hostName;

  // get name of own machine
  if (gethostname(szHostname, sizeof(szHostname))!=0) {
    hostName="_unknown_";
  }
  else {
    // get host entry
    pHostEnt = gethostbyname(szHostname);
    // return fully qualified name of machine as ID
    if (pHostEnt)
      hostName=pHostEnt->h_name; // DNS name of machine
    else
      hostName=szHostname; // just name of machine
  }
  // generate URI from name
  #ifdef ANDROID
  aURI="android:";
  #else
  aURI="linux:"; // %%% SCTS does not like http:// here, so we take os:xxxx
  #endif
  // add name of this machine (fully qualified if possible)
  aURI+=hostName;
  // this is more or less unique
  return true;
} // getLocalDeviceID


// write to platform's "console", whatever that is
void PlatformConsolePuts(const char *aText)
{
  // generic output
  #ifdef ANDROID
    __android_log_write( ANDROID_LOG_DEBUG, "ConsolePuts", aText );
  #else
    puts(aText); // appends newline itself
  #endif
} // PlatformConsolePuts



/* eof */