vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / file_systems / nfs4 / MetadataCache.cpp
blobcd4f479d97fd2fd51b0e174c2f755ded20ea015f
1 /*
2 * Copyright 2012-2016 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Paweł Dziepak, pdziepak@quarnos.org
7 */
10 #include "MetadataCache.h"
12 #include <NodeMonitor.h>
14 #include "Inode.h"
17 MetadataCache::MetadataCache(Inode* inode)
19 fExpire(0),
20 fForceValid(false),
21 fInode(inode),
22 fInited(false)
24 ASSERT(inode != NULL);
25 mutex_init(&fLock, NULL);
29 MetadataCache::~MetadataCache()
31 mutex_destroy(&fLock);
35 status_t
36 MetadataCache::GetStat(struct stat* st)
38 ASSERT(st != NULL);
40 MutexLocker _(fLock);
41 if (fForceValid || fExpire > time(NULL)) {
42 // Do not touch other members of struct stat
43 st->st_size = fStatCache.st_size;
44 st->st_mode = fStatCache.st_mode;
45 st->st_nlink = fStatCache.st_nlink;
46 st->st_uid = fStatCache.st_uid;
47 st->st_gid = fStatCache.st_gid;
48 st->st_atim = fStatCache.st_atim;
49 st->st_ctim = fStatCache.st_ctim;
50 st->st_crtim = fStatCache.st_crtim;
51 st->st_mtim = fStatCache.st_mtim;
52 st->st_blksize = fStatCache.st_blksize;
53 st->st_blocks = fStatCache.st_blocks;
54 return B_OK;
57 return B_ERROR;
61 void
62 MetadataCache::SetStat(const struct stat& st)
64 MutexLocker _(fLock);
65 if (fInited)
66 NotifyChanges(&fStatCache, &st);
68 fStatCache = st;
69 fExpire = time(NULL) + kExpirationTime;
70 fInited = true;
74 void
75 MetadataCache::GrowFile(size_t newSize)
77 MutexLocker _(fLock);
78 off_t oldSize = fStatCache.st_size;
79 fStatCache.st_size = max_c((off_t)newSize, fStatCache.st_size);
81 if (oldSize != fStatCache.st_size) {
82 notify_stat_changed(fInode->GetFileSystem()->DevId(), -1, fInode->ID(),
83 B_STAT_SIZE);
88 status_t
89 MetadataCache::GetAccess(uid_t uid, uint32* allowed)
91 ASSERT(allowed != NULL);
93 MutexLocker _(fLock);
94 AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid);
95 if (!it.HasCurrent())
96 return B_ENTRY_NOT_FOUND;
98 if (!fForceValid)
99 it.CurrentValuePointer()->fForceValid = false;
101 if (!it.Current().fForceValid && it.Current().fExpire < time(NULL)) {
102 it.Remove();
103 return B_ERROR;
106 *allowed = it.Current().fAllowed;
108 return B_OK;
112 void
113 MetadataCache::SetAccess(uid_t uid, uint32 allowed)
115 MutexLocker _(fLock);
116 AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid);
117 if (it.HasCurrent())
118 it.Remove();
120 AccessEntry entry;
121 entry.fAllowed = allowed;
122 entry.fExpire = time(NULL) + kExpirationTime;
123 entry.fForceValid = fForceValid;
125 fAccessCache.Insert(uid, entry);
129 status_t
130 MetadataCache::LockValid()
132 MutexLocker _(fLock);
133 if (fForceValid || fExpire > time(NULL)) {
134 fForceValid = true;
135 return B_OK;
138 return B_ERROR;
142 void
143 MetadataCache::UnlockValid()
145 MutexLocker _(fLock);
146 fExpire = time(NULL) + kExpirationTime;
147 fForceValid = false;
151 void
152 MetadataCache::NotifyChanges(const struct stat* oldStat,
153 const struct stat* newStat)
155 ASSERT(oldStat != NULL);
156 ASSERT(newStat != NULL);
158 uint32 flags = 0;
159 if (oldStat->st_size != newStat->st_size)
160 flags |= B_STAT_SIZE;
161 if (oldStat->st_mode != newStat->st_mode)
162 flags |= B_STAT_MODE;
163 if (oldStat->st_uid != newStat->st_uid)
164 flags |= B_STAT_UID;
165 if (oldStat->st_gid != newStat->st_gid)
166 flags |= B_STAT_GID;
168 if (memcmp(&oldStat->st_atim, &newStat->st_atim,
169 sizeof(struct timespec) == 0))
170 flags |= B_STAT_ACCESS_TIME;
172 if (memcmp(&oldStat->st_ctim, &newStat->st_ctim,
173 sizeof(struct timespec) == 0))
174 flags |= B_STAT_CHANGE_TIME;
176 if (memcmp(&oldStat->st_crtim, &newStat->st_crtim,
177 sizeof(struct timespec) == 0))
178 flags |= B_STAT_CREATION_TIME;
180 if (memcmp(&oldStat->st_mtim, &newStat->st_mtim,
181 sizeof(struct timespec) == 0))
182 flags |= B_STAT_MODIFICATION_TIME;
184 notify_stat_changed(fInode->GetFileSystem()->DevId(), -1, fInode->ID(),
185 flags);