1*f8e2c85aSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*f8e2c85aSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*f8e2c85aSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*f8e2c85aSAndrew Rist * distributed with this work for additional information 6*f8e2c85aSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*f8e2c85aSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*f8e2c85aSAndrew Rist * "License"); you may not use this file except in compliance 9*f8e2c85aSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*f8e2c85aSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*f8e2c85aSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*f8e2c85aSAndrew Rist * software distributed under the License is distributed on an 15*f8e2c85aSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*f8e2c85aSAndrew Rist * KIND, either express or implied. See the License for the 17*f8e2c85aSAndrew Rist * specific language governing permissions and limitations 18*f8e2c85aSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*f8e2c85aSAndrew Rist *************************************************************/ 21*f8e2c85aSAndrew Rist 22*f8e2c85aSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_shell.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #ifndef INCLUDED_RECENTLY_USED_FILE 28cdf0e10cSrcweir #include "recently_used_file.hxx" 29cdf0e10cSrcweir #endif 30cdf0e10cSrcweir #include <rtl/ustring.hxx> 31cdf0e10cSrcweir #include <osl/process.h> 32cdf0e10cSrcweir #include <osl/security.hxx> 33cdf0e10cSrcweir #include <osl/thread.h> 34cdf0e10cSrcweir #include <osl/file.hxx> 35cdf0e10cSrcweir 36cdf0e10cSrcweir #include <sys/file.h> 37cdf0e10cSrcweir #include <sys/types.h> 38cdf0e10cSrcweir #include <sys/stat.h> 39cdf0e10cSrcweir 40cdf0e10cSrcweir #include <unistd.h> 41cdf0e10cSrcweir 42cdf0e10cSrcweir const rtl::OUString RECENTLY_USED_FILE_NAME = rtl::OUString::createFromAscii(".recently-used"); 43cdf0e10cSrcweir const rtl::OUString SLASH = rtl::OUString::createFromAscii("/"); 44cdf0e10cSrcweir 45cdf0e10cSrcweir namespace /* private */ { 46cdf0e10cSrcweir 47cdf0e10cSrcweir inline void ensure_final_slash(/*inout*/ rtl::OUString& path) 48cdf0e10cSrcweir { 49cdf0e10cSrcweir if ((path.getLength() > 0) && 50cdf0e10cSrcweir (SLASH.pData->buffer[0] != path.pData->buffer[path.getLength() - 1])) 51cdf0e10cSrcweir path += SLASH; 52cdf0e10cSrcweir } 53cdf0e10cSrcweir 54cdf0e10cSrcweir } // namespace private 55cdf0e10cSrcweir 56cdf0e10cSrcweir //------------------------------------------------ 57cdf0e10cSrcweir recently_used_file::recently_used_file() : 58cdf0e10cSrcweir file_(NULL) 59cdf0e10cSrcweir { 60cdf0e10cSrcweir osl::Security sec; 61cdf0e10cSrcweir rtl::OUString homedir_url; 62cdf0e10cSrcweir 63cdf0e10cSrcweir if (sec.getHomeDir(homedir_url)) 64cdf0e10cSrcweir { 65cdf0e10cSrcweir rtl::OUString homedir; 66cdf0e10cSrcweir osl::FileBase::getSystemPathFromFileURL(homedir_url, homedir); 67cdf0e10cSrcweir 68cdf0e10cSrcweir rtl::OUString rufn = homedir; 69cdf0e10cSrcweir ensure_final_slash(rufn); 70cdf0e10cSrcweir rufn += RECENTLY_USED_FILE_NAME; 71cdf0e10cSrcweir 72cdf0e10cSrcweir rtl::OString tmp = 73cdf0e10cSrcweir rtl::OUStringToOString(rufn, osl_getThreadTextEncoding()); 74cdf0e10cSrcweir 75cdf0e10cSrcweir file_ = fopen(tmp.getStr(), "r+"); 76cdf0e10cSrcweir 77cdf0e10cSrcweir /* create if not exist */ 78cdf0e10cSrcweir if (NULL == file_) { 79cdf0e10cSrcweir mode_t umask_ = umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 80cdf0e10cSrcweir file_ = fopen(tmp.getStr(), "w+"); 81cdf0e10cSrcweir umask(umask_); 82cdf0e10cSrcweir } 83cdf0e10cSrcweir 84cdf0e10cSrcweir if (NULL == file_) 85cdf0e10cSrcweir throw "I/O error opening ~/.recently-used"; 86cdf0e10cSrcweir 87cdf0e10cSrcweir if (lockf(fileno(file_), F_LOCK, 0) != 0) 88cdf0e10cSrcweir { 89cdf0e10cSrcweir fclose(file_); 90cdf0e10cSrcweir throw "Cannot lock ~/.recently-used"; 91cdf0e10cSrcweir } 92cdf0e10cSrcweir } 93cdf0e10cSrcweir else 94cdf0e10cSrcweir throw "Cannot determine user home directory"; 95cdf0e10cSrcweir } 96cdf0e10cSrcweir 97cdf0e10cSrcweir //------------------------------------------------ 98cdf0e10cSrcweir recently_used_file::~recently_used_file() 99cdf0e10cSrcweir { 100cdf0e10cSrcweir lockf(fileno(file_), F_ULOCK, 0); 101cdf0e10cSrcweir fclose(file_); 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir //------------------------------------------------ 105cdf0e10cSrcweir void recently_used_file::reset() const 106cdf0e10cSrcweir { 107cdf0e10cSrcweir rewind(file_); 108cdf0e10cSrcweir } 109cdf0e10cSrcweir 110cdf0e10cSrcweir //------------------------------------------------ 111cdf0e10cSrcweir void recently_used_file::truncate(off_t length) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir if (ftruncate(fileno(file_), length) == -1) 114cdf0e10cSrcweir throw "I/O error: ftruncate failed"; 115cdf0e10cSrcweir } 116cdf0e10cSrcweir 117cdf0e10cSrcweir //------------------------------------------------ 118cdf0e10cSrcweir size_t recently_used_file::read(char* buffer, size_t size) const 119cdf0e10cSrcweir { 120cdf0e10cSrcweir size_t r = fread(reinterpret_cast<void*>(buffer), sizeof(char), size, file_); 121cdf0e10cSrcweir 122cdf0e10cSrcweir if ((r < size) && ferror(file_)) 123cdf0e10cSrcweir throw "I/O error: read failed"; 124cdf0e10cSrcweir 125cdf0e10cSrcweir return r; 126cdf0e10cSrcweir } 127cdf0e10cSrcweir 128cdf0e10cSrcweir //---------------------------- 129cdf0e10cSrcweir void recently_used_file::write(const char* buffer, size_t size) const 130cdf0e10cSrcweir { 131cdf0e10cSrcweir if (size != fwrite(reinterpret_cast<const void*>(buffer), sizeof(char), size, file_)) 132cdf0e10cSrcweir throw "I/O error: write failed"; 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir //---------------------------- 136cdf0e10cSrcweir bool recently_used_file::eof() const 137cdf0e10cSrcweir { 138cdf0e10cSrcweir return feof(file_); 139cdf0e10cSrcweir } 140cdf0e10cSrcweir 141cdf0e10cSrcweir 142cdf0e10cSrcweir 143cdf0e10cSrcweir 144