15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_file_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace base {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deny |permission| on the file |path|.
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool DenyFilePermission(const FilePath& path, mode_t permission) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat stat_buf;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stat(path.value().c_str(), &stat_buf) != 0)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_buf.st_mode &= ~permission;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = HANDLE_EINTR(chmod(path.value().c_str(), stat_buf.st_mode));
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv == 0;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets a blob indicating the permission information for |path|.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |length| is the length of the blob.  Zero on failure.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the blob pointer, or NULL on failure.
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void* GetPermissionInfo(const FilePath& path, size_t* length) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(length);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *length = 0;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat stat_buf;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stat(path.value().c_str(), &stat_buf) != 0)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *length = sizeof(mode_t);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode_t* mode = new mode_t;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *mode = stat_buf.st_mode & ~S_IFMT;  // Filter out file/path kind.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return mode;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Restores the permission information for |path|, given the blob retrieved
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using |GetPermissionInfo()|.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |info| is the pointer to the blob.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |length| is the length of the blob.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Either |info| or |length| may be NULL/0, in which case nothing happens.
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RestorePermissionInfo(const FilePath& path, void* info, size_t length) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info || (length == 0))
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(sizeof(mode_t), length);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode_t* mode = reinterpret_cast<mode_t*>(info);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = HANDLE_EINTR(chmod(path.value().c_str(), *mode));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete mode;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv == 0;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool DieFileDie(const FilePath& file, bool recurse) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no need to workaround Windows problems on POSIX.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Just pass-through.
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return DeleteFile(file, recurse);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_LINUX) && !defined(OS_MACOSX)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool EvictFileFromSystemCache(const FilePath& file) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There doesn't seem to be a POSIX way to cool the disk cache.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool MakeFileUnreadable(const FilePath& path) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DenyFilePermission(path, S_IRUSR | S_IRGRP | S_IROTH);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool MakeFileUnwritable(const FilePath& path) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DenyFilePermission(path, S_IWUSR | S_IWGRP | S_IWOTH);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)FilePermissionRestorer::FilePermissionRestorer(const FilePath& path)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : path_(path), info_(NULL), length_(0) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info_ = GetPermissionInfo(path_, &length_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(info_ != NULL);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0u, length_);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)FilePermissionRestorer::~FilePermissionRestorer() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!RestorePermissionInfo(path_, info_, length_))
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace base
109