1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "testsupport/fileutils.h"
12
13#ifdef WIN32
14#include <direct.h>
15#define GET_CURRENT_DIR _getcwd
16#else
17#include <unistd.h>
18#define GET_CURRENT_DIR getcwd
19#endif
20
21#include <sys/stat.h>  // To check for directory existence.
22#ifndef S_ISDIR  // Not defined in stat.h on Windows.
23#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
24#endif
25
26#include <cstdio>
27
28#include "typedefs.h"  // For architecture defines
29
30namespace webrtc {
31namespace test {
32
33#ifdef WIN32
34static const char* kPathDelimiter = "\\";
35#else
36static const char* kPathDelimiter = "/";
37#endif
38// The file we're looking for to identify the project root dir.
39static const char* kProjectRootFileName = "DEPS";
40static const char* kOutputDirName = "out";
41static const char* kFallbackPath = "./";
42static const char* kResourcesDirName = "resources";
43const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
44
45std::string ProjectRootPath() {
46  std::string working_dir = WorkingDir();
47  if (working_dir == kFallbackPath) {
48    return kCannotFindProjectRootDir;
49  }
50  // Check for our file that verifies the root dir.
51  std::string current_path(working_dir);
52  FILE* file = NULL;
53  int path_delimiter_index = current_path.find_last_of(kPathDelimiter);
54  while (path_delimiter_index > -1) {
55    std::string root_filename = current_path + kPathDelimiter +
56        kProjectRootFileName;
57    file = fopen(root_filename.c_str(), "r");
58    if (file != NULL) {
59      fclose(file);
60      return current_path + kPathDelimiter;
61    }
62    // Move up one directory in the directory tree.
63    current_path = current_path.substr(0, path_delimiter_index);
64    path_delimiter_index = current_path.find_last_of(kPathDelimiter);
65  }
66  // Reached the root directory.
67  fprintf(stderr, "Cannot find project root directory!\n");
68  return kCannotFindProjectRootDir;
69}
70
71std::string OutputPath() {
72  std::string path = ProjectRootPath();
73  if (path == kCannotFindProjectRootDir) {
74    return kFallbackPath;
75  }
76  path += kOutputDirName;
77  if (!CreateDirectory(path)) {
78    return kFallbackPath;
79  }
80  return path + kPathDelimiter;
81}
82
83std::string WorkingDir() {
84  char path_buffer[FILENAME_MAX];
85  if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
86    fprintf(stderr, "Cannot get current directory!\n");
87    return kFallbackPath;
88  } else {
89    return std::string(path_buffer);
90  }
91}
92
93bool CreateDirectory(std::string directory_name) {
94  struct stat path_info = {0};
95  // Check if the path exists already:
96  if (stat(directory_name.c_str(), &path_info) == 0) {
97    if (!S_ISDIR(path_info.st_mode)) {
98      fprintf(stderr, "Path %s exists but is not a directory! Remove this "
99              "file and re-run to create the directory.\n",
100              directory_name.c_str());
101      return false;
102    }
103  } else {
104#ifdef WIN32
105    return _mkdir(directory_name.c_str()) == 0;
106#else
107    return mkdir(directory_name.c_str(),  S_IRWXU | S_IRWXG | S_IRWXO) == 0;
108#endif
109  }
110  return true;
111}
112
113bool FileExists(std::string file_name) {
114  struct stat file_info = {0};
115  return stat(file_name.c_str(), &file_info) == 0;
116}
117
118std::string ResourcePath(std::string name, std::string extension) {
119  std::string platform = "win";
120#ifdef WEBRTC_LINUX
121  platform = "linux";
122#endif  // WEBRTC_LINUX
123#ifdef WEBRTC_MAC
124  platform = "mac";
125#endif  // WEBRTC_MAC
126
127#ifdef WEBRTC_ARCH_64_BITS
128  std::string architecture = "64";
129#else
130  std::string architecture = "32";
131#endif  // WEBRTC_ARCH_64_BITS
132
133  std::string resources_path = ProjectRootPath() + kResourcesDirName +
134      kPathDelimiter;
135  std::string resource_file = resources_path + name + "_" + platform + "_" +
136      architecture + "." + extension;
137  if (FileExists(resource_file)) {
138    return resource_file;
139  }
140  // Try without architecture.
141  resource_file = resources_path + name + "_" + platform + "." + extension;
142  if (FileExists(resource_file)) {
143    return resource_file;
144  }
145  // Try without platform.
146  resource_file = resources_path + name + "_" + architecture + "." + extension;
147  if (FileExists(resource_file)) {
148    return resource_file;
149  }
150  // Fall back on name without architecture or platform.
151  return resources_path + name + "." + extension;
152}
153
154size_t GetFileSize(std::string filename) {
155  FILE* f = fopen(filename.c_str(), "rb");
156  size_t size = 0;
157  if (f != NULL) {
158    if (fseek(f, 0, SEEK_END) == 0) {
159      size = ftell(f);
160    }
161    fclose(f);
162  }
163  return size;
164}
165
166}  // namespace test
167}  // namespace webrtc
168