The Pedigree Project 0.1
Symlink.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "Symlink.h"
21#include "pedigree/kernel/LockGuard.h"
22#include "pedigree/kernel/utilities/utility.h"
23
24#include "Filesystem.h"
25#include "VFS.h"
26
27Symlink::Symlink() : File(), m_sTarget(), m_TargetLock() {}
28
29Symlink::Symlink(const String& name, Time::Timestamp accessedTime, Time::Timestamp modifiedTime,
30 Time::Timestamp creationTime, uintptr_t inode, Filesystem* pFs, size_t size,
31 File* pParent)
32 : File(name, accessedTime, modifiedTime, creationTime, inode, pFs, size, pParent),
33 m_sTarget(),
34 m_TargetLock() {}
35
37
39 if (!VFS::instance().retainTrackedFile(target))
40 return nullptr;
41 Directory::ChildLease replacement;
42 replacement.adopt(target);
43 result.swap(replacement);
44 return target;
45}
46
47void Symlink::initialise(bool bForce) {
48 if (m_sTarget.length() && !bForce)
49 return;
50
51 size_t sz = getSize();
52 if (sz > 0x1000)
53 sz = 0x1000;
54 if (!sz) {
55 m_sTarget.clear();
56 return;
57 }
58
59 // Read symlink target.
60 char* pBuffer = new char[sz];
61 const size_t bytesRead = read(0ULL, sz, reinterpret_cast<uintptr_t>(pBuffer));
62
63 // Convert to String object, wipe out whitespace.
64 if (bytesRead) {
65 m_sTarget.assign(pBuffer, bytesRead, true);
66 } else {
67 m_sTarget.clear();
68 }
69 m_sTarget.rstrip();
70 delete[] pBuffer;
71}
72
74 ParentLease parentLease;
75 String unusedName;
76 getNamespace(parentLease, unusedName);
77 File* parent = parentLease.get();
78
79 String target;
80 {
82 initialise();
83 target = m_sTarget;
84 }
85 if (target.length() && target[0] == '/')
86 return VFS::instance().findRetained(target, result);
87 return m_pFilesystem->findRetained(target.view(), result, parent);
88}
89
90int Symlink::followLink(char* pBuffer, size_t bufLen) {
92 initialise();
93
94 if (m_sTarget.length() < bufLen)
95 bufLen = m_sTarget.length();
96
97 StringCopyN(pBuffer, static_cast<const char*>(m_sTarget), bufLen);
98
99 return bufLen;
100}
101
103 return true;
104}
Definition File.h:75
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
Definition File.cc:239
void getNamespace(ParentLease &parent, String &name) const
Definition File.cc:992
File * findRetained(const StringView &path, Directory::ChildLease &result, File *pStartNode=nullptr)
StringView view() const
Definition String.cc:783
void rstrip()
Definition String.cc:507
File * findRetained(const String &path, Directory::ChildLease &result, File *pStartNode=nullptr)
Definition VFS.cc:1042
static VFS & instance()
Definition VFS.cc:311