1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 <sys/stat.h>
10#include <sys/types.h>
11
12#include <string>
13
14#include "base/files/file_path.h"
15#include "base/files/file_util.h"
16#include "base/logging.h"
17#include "base/strings/string_util.h"
18#include "base/strings/utf_string_conversions.h"
19
20namespace base {
21
22namespace {
23
24// Deny |permission| on the file |path|.
25bool DenyFilePermission(const FilePath& path, mode_t permission) {
26  struct stat stat_buf;
27  if (stat(path.value().c_str(), &stat_buf) != 0)
28    return false;
29  stat_buf.st_mode &= ~permission;
30
31  int rv = HANDLE_EINTR(chmod(path.value().c_str(), stat_buf.st_mode));
32  return rv == 0;
33}
34
35// Gets a blob indicating the permission information for |path|.
36// |length| is the length of the blob.  Zero on failure.
37// Returns the blob pointer, or NULL on failure.
38void* GetPermissionInfo(const FilePath& path, size_t* length) {
39  DCHECK(length);
40  *length = 0;
41
42  struct stat stat_buf;
43  if (stat(path.value().c_str(), &stat_buf) != 0)
44    return NULL;
45
46  *length = sizeof(mode_t);
47  mode_t* mode = new mode_t;
48  *mode = stat_buf.st_mode & ~S_IFMT;  // Filter out file/path kind.
49
50  return mode;
51}
52
53// Restores the permission information for |path|, given the blob retrieved
54// using |GetPermissionInfo()|.
55// |info| is the pointer to the blob.
56// |length| is the length of the blob.
57// Either |info| or |length| may be NULL/0, in which case nothing happens.
58bool RestorePermissionInfo(const FilePath& path, void* info, size_t length) {
59  if (!info || (length == 0))
60    return false;
61
62  DCHECK_EQ(sizeof(mode_t), length);
63  mode_t* mode = reinterpret_cast<mode_t*>(info);
64
65  int rv = HANDLE_EINTR(chmod(path.value().c_str(), *mode));
66
67  delete mode;
68
69  return rv == 0;
70}
71
72}  // namespace
73
74bool DieFileDie(const FilePath& file, bool recurse) {
75  // There is no need to workaround Windows problems on POSIX.
76  // Just pass-through.
77  return DeleteFile(file, recurse);
78}
79
80#if !defined(OS_LINUX) && !defined(OS_MACOSX)
81bool EvictFileFromSystemCache(const FilePath& file) {
82  // There doesn't seem to be a POSIX way to cool the disk cache.
83  NOTIMPLEMENTED();
84  return false;
85}
86#endif
87
88bool MakeFileUnreadable(const FilePath& path) {
89  return DenyFilePermission(path, S_IRUSR | S_IRGRP | S_IROTH);
90}
91
92bool MakeFileUnwritable(const FilePath& path) {
93  return DenyFilePermission(path, S_IWUSR | S_IWGRP | S_IWOTH);
94}
95
96FilePermissionRestorer::FilePermissionRestorer(const FilePath& path)
97    : path_(path), info_(NULL), length_(0) {
98  info_ = GetPermissionInfo(path_, &length_);
99  DCHECK(info_ != NULL);
100  DCHECK_NE(0u, length_);
101}
102
103FilePermissionRestorer::~FilePermissionRestorer() {
104  if (!RestorePermissionInfo(path_, info_, length_))
105    NOTREACHED();
106}
107
108}  // namespace base
109