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 m_sTarget.assign(pBuffer, bytesRead);
65 m_sTarget.rstrip();
66 delete[] pBuffer;
67}
68
70 ParentLease parentLease;
71 String unusedName;
72 getNamespace(parentLease, unusedName);
73 File* parent = parentLease.get();
74
75 String target;
76 {
78 initialise();
79 target = m_sTarget;
80 }
81 if (target.length() && target[0] == '/')
82 return VFS::instance().findRetained(target, result);
83 return m_pFilesystem->findRetained(target.view(), result, parent);
84}
85
86int Symlink::followLink(char* pBuffer, size_t bufLen) {
88 initialise();
89
90 if (m_sTarget.length() < bufLen)
91 bufLen = m_sTarget.length();
92
93 StringCopyN(pBuffer, static_cast<const char*>(m_sTarget), bufLen);
94
95 return bufLen;
96}
97
98bool Symlink::isBytewise() const {
99 return true;
100}
Definition File.h:74
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
Definition File.cc:230
void getNamespace(ParentLease &parent, String &name) const
Definition File.cc:893
File * findRetained(const StringView &path, Directory::ChildLease &result, File *pStartNode=nullptr)
StringView view() const
Definition String.cc:768
void rstrip()
Definition String.cc:492
File * findRetained(const String &path, Directory::ChildLease &result, File *pStartNode=nullptr)
Definition VFS.cc:932
static VFS & instance()
Definition VFS.cc:310