1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/test/test_file_util.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stddef.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include <string>
14
15 #include "base/check_op.h"
16 #include "base/files/file.h"
17 #include "base/files/file_util.h"
18 #include "base/notreached.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "build/build_config.h"
22
23 namespace base {
24
25 namespace {
26
27 // Deny |permission| on the file |path|.
DenyFilePermission(const FilePath & path,mode_t permission)28 bool DenyFilePermission(const FilePath& path, mode_t permission) {
29 stat_wrapper_t stat_buf;
30 if (File::Stat(path.value().c_str(), &stat_buf) != 0)
31 return false;
32 stat_buf.st_mode &= ~permission;
33
34 int rv = HANDLE_EINTR(chmod(path.value().c_str(), stat_buf.st_mode));
35 return rv == 0;
36 }
37
38 // Gets a blob indicating the permission information for |path|.
39 // |length| is the length of the blob. Zero on failure.
40 // Returns the blob pointer, or NULL on failure.
GetPermissionInfo(const FilePath & path,size_t * length)41 void* GetPermissionInfo(const FilePath& path, size_t* length) {
42 DCHECK(length);
43 *length = 0;
44
45 stat_wrapper_t stat_buf;
46 if (File::Stat(path.value().c_str(), &stat_buf) != 0)
47 return nullptr;
48
49 *length = sizeof(mode_t);
50 mode_t* mode = new mode_t;
51 *mode = stat_buf.st_mode & ~S_IFMT; // Filter out file/path kind.
52
53 return mode;
54 }
55
56 // Restores the permission information for |path|, given the blob retrieved
57 // using |GetPermissionInfo()|.
58 // |info| is the pointer to the blob.
59 // |length| is the length of the blob.
60 // Either |info| or |length| may be NULL/0, in which case nothing happens.
RestorePermissionInfo(const FilePath & path,void * info,size_t length)61 bool RestorePermissionInfo(const FilePath& path, void* info, size_t length) {
62 if (!info || (length == 0))
63 return false;
64
65 DCHECK_EQ(sizeof(mode_t), length);
66 mode_t* mode = reinterpret_cast<mode_t*>(info);
67
68 int rv = HANDLE_EINTR(chmod(path.value().c_str(), *mode));
69
70 delete mode;
71
72 return rv == 0;
73 }
74
75 } // namespace
76
DieFileDie(const FilePath & file,bool recurse)77 bool DieFileDie(const FilePath& file, bool recurse) {
78 // There is no need to workaround Windows problems on POSIX.
79 // Just pass-through.
80 if (recurse)
81 return DeletePathRecursively(file);
82 return DeleteFile(file);
83 }
84
SyncPageCacheToDisk()85 void SyncPageCacheToDisk() {
86 // On Linux (and Android) the sync(2) call waits for I/O completions.
87 sync();
88 }
89
90 #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_APPLE) && \
91 !BUILDFLAG(IS_ANDROID)
EvictFileFromSystemCache(const FilePath & file)92 bool EvictFileFromSystemCache(const FilePath& file) {
93 // There doesn't seem to be a POSIX way to cool the disk cache.
94 NOTIMPLEMENTED();
95 return false;
96 }
97 #endif
98
MakeFileUnreadable(const FilePath & path)99 bool MakeFileUnreadable(const FilePath& path) {
100 return DenyFilePermission(path, S_IRUSR | S_IRGRP | S_IROTH);
101 }
102
MakeFileUnwritable(const FilePath & path)103 bool MakeFileUnwritable(const FilePath& path) {
104 return DenyFilePermission(path, S_IWUSR | S_IWGRP | S_IWOTH);
105 }
106
FilePermissionRestorer(const FilePath & path)107 FilePermissionRestorer::FilePermissionRestorer(const FilePath& path)
108 : path_(path), info_(nullptr), length_(0) {
109 info_ = GetPermissionInfo(path_, &length_);
110 DCHECK(info_ != nullptr);
111 DCHECK_NE(0u, length_);
112 }
113
~FilePermissionRestorer()114 FilePermissionRestorer::~FilePermissionRestorer() {
115 if (!RestorePermissionInfo(path_, info_, length_))
116 NOTREACHED();
117 }
118
119 } // namespace base
120