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
ensure_final_slash(rtl::OUString & path)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 //------------------------------------------------
recently_used_file()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 //------------------------------------------------
~recently_used_file()98cdf0e10cSrcweir recently_used_file::~recently_used_file()
99cdf0e10cSrcweir {
100cdf0e10cSrcweir lockf(fileno(file_), F_ULOCK, 0);
101cdf0e10cSrcweir fclose(file_);
102cdf0e10cSrcweir }
103cdf0e10cSrcweir
104cdf0e10cSrcweir //------------------------------------------------
reset() const105cdf0e10cSrcweir void recently_used_file::reset() const
106cdf0e10cSrcweir {
107cdf0e10cSrcweir rewind(file_);
108cdf0e10cSrcweir }
109cdf0e10cSrcweir
110cdf0e10cSrcweir //------------------------------------------------
truncate(off_t length)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 //------------------------------------------------
read(char * buffer,size_t size) const118cdf0e10cSrcweir 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 //----------------------------
write(const char * buffer,size_t size) const129cdf0e10cSrcweir 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 //----------------------------
eof() const136cdf0e10cSrcweir bool recently_used_file::eof() const
137cdf0e10cSrcweir {
138cdf0e10cSrcweir return feof(file_);
139cdf0e10cSrcweir }
140cdf0e10cSrcweir
141cdf0e10cSrcweir
142cdf0e10cSrcweir
143cdf0e10cSrcweir
144