3 #include "AllocationInfo.h"
5 #include "EntryIterator.h"
6 #include "LastModifiedIndex.h"
13 is_user_in_group(gid_t gid
)
15 // Either I miss something, or we don't have getgroups() in the kernel. :-(
17 gid_t groups[NGROUPS_MAX];
18 int groupCount = getgroups(NGROUPS_MAX, groups);
19 for (int i = 0; i < groupCount; i++) {
24 return (gid
== getegid());
29 Node::Node(Volume
*volume
, uint8 type
)
31 fID(fVolume
->NextNodeID()),
42 // attribute management
49 case NODE_TYPE_DIRECTORY
:
55 case NODE_TYPE_SYMLINK
:
59 // set defaults for time
60 fATime
= fMTime
= fCTime
= fCrTime
= time(NULL
);
66 // delete all attributes
67 while (Attribute
*attribute
= fAttributes
.First()) {
68 status_t error
= DeleteAttribute(attribute
);
70 FATAL(("Node::~Node(): Failed to delete attribute!\n"));
78 Node::InitCheck() const
80 return (fVolume
&& fID
>= 0 ? B_OK
: B_NO_INIT
);
87 if (++fRefCount
== 1) {
88 status_t error
= GetVolume()->PublishVNode(this);
102 Node::RemoveReference()
104 if (--fRefCount
== 0) {
105 GetVolume()->RemoveVNode(this);
112 Node::Link(Entry
*entry
)
114 PRINT(("Node[%Ld]::Link(): %ld ->...\n", fID
, fRefCount
));
115 fReferrers
.Insert(entry
);
117 status_t error
= AddReference();
119 fReferrers
.Remove(entry
);
126 Node::Unlink(Entry
*entry
)
128 PRINT(("Node[%Ld]::Unlink(): %ld ->...\n", fID
, fRefCount
));
130 fReferrers
.Remove(entry
);
137 Node::SetMTime(time_t mTime
)
139 time_t oldMTime
= fMTime
;
140 fATime
= fMTime
= mTime
;
141 if (oldMTime
!= fMTime
) {
142 if (LastModifiedIndex
*index
= fVolume
->GetLastModifiedIndex())
143 index
->Changed(this, oldMTime
);
149 Node::CheckPermissions(int mode
) const
151 int userPermissions
= (fMode
& S_IRWXU
) >> 6;
152 int groupPermissions
= (fMode
& S_IRWXG
) >> 3;
153 int otherPermissions
= fMode
& S_IRWXO
;
154 // get the permissions for this uid/gid
156 uid_t uid
= geteuid();
159 // root has always read/write permission, but at least one of the
160 // X bits must be set for execute permission
161 permissions
= userPermissions
| groupPermissions
| otherPermissions
162 | ACCESS_R
| ACCESS_W
;
163 // user is node owner
164 } else if (uid
== fUID
)
165 permissions
= userPermissions
;
166 // user is in owning group
167 else if (is_user_in_group(fGID
))
168 permissions
= groupPermissions
;
169 // user is one of the others
171 permissions
= otherPermissions
;
173 return ((mode
& ~permissions
) ? B_NOT_ALLOWED
: B_OK
);
178 Node::CreateAttribute(const char *name
, Attribute
**_attribute
)
180 status_t error
= (name
&& _attribute
? B_OK
: B_BAD_VALUE
);
183 Attribute
*attribute
= new(nothrow
) Attribute(fVolume
, NULL
, name
);
185 error
= attribute
->InitCheck();
187 // add attribute to node
188 error
= AddAttribute(attribute
);
190 *_attribute
= attribute
;
195 SET_ERROR(error
, B_NO_MEMORY
);
202 Node::DeleteAttribute(Attribute
*attribute
)
204 status_t error
= RemoveAttribute(attribute
);
212 Node::AddAttribute(Attribute
*attribute
)
214 status_t error
= (attribute
&& !attribute
->GetNode() ? B_OK
: B_BAD_VALUE
);
216 error
= GetVolume()->NodeAttributeAdded(GetID(), attribute
);
218 fAttributes
.Insert(attribute
);
219 attribute
->SetNode(this);
220 MarkModified(B_STAT_MODIFICATION_TIME
);
228 Node::RemoveAttribute(Attribute
*attribute
)
230 status_t error
= (attribute
&& attribute
->GetNode() == this
231 ? B_OK
: B_BAD_VALUE
);
233 // move all iterators pointing to the attribute to the next attribute
234 if (GetVolume()->IteratorLock()) {
235 // set the iterators' current entry
236 Attribute
*nextAttr
= fAttributes
.GetNext(attribute
);
237 DoublyLinkedList
<AttributeIterator
> *iterators
238 = attribute
->GetAttributeIteratorList();
239 for (AttributeIterator
*iterator
= iterators
->First();
241 iterator
= iterators
->GetNext(iterator
)) {
242 iterator
->SetCurrent(nextAttr
, true);
244 // Move the iterators from one list to the other, or just remove
245 // them, if there is no next attribute.
247 DoublyLinkedList
<AttributeIterator
> *nextIterators
248 = nextAttr
->GetAttributeIteratorList();
249 nextIterators
->MoveFrom(iterators
);
251 iterators
->RemoveAll();
252 GetVolume()->IteratorUnlock();
255 // remove the attribute
257 error
= GetVolume()->NodeAttributeRemoved(GetID(), attribute
);
259 fAttributes
.Remove(attribute
);
260 attribute
->SetNode(NULL
);
261 MarkModified(B_STAT_MODIFICATION_TIME
);
270 Node::FindAttribute(const char *name
, Attribute
**_attribute
) const
272 status_t error
= (name
&& _attribute
? B_OK
: B_BAD_VALUE
);
275 Attribute *attribute = NULL;
276 while (GetNextAttribute(&attribute) == B_OK) {
277 if (!strcmp(attribute->GetName(), name)) {
278 *_attribute = attribute;
282 error = B_ENTRY_NOT_FOUND;
284 error
= GetVolume()->FindNodeAttribute(GetID(), name
, _attribute
);
289 // GetPreviousAttribute
291 Node::GetPreviousAttribute(Attribute
**attribute
) const
293 status_t error
= (attribute
? B_OK
: B_BAD_VALUE
);
296 *attribute
= fAttributes
.Last();
297 else if ((*attribute
)->GetNode() == this)
298 *attribute
= fAttributes
.GetPrevious(*attribute
);
301 if (error
== B_OK
&& !*attribute
)
302 error
= B_ENTRY_NOT_FOUND
;
309 Node::GetNextAttribute(Attribute
**attribute
) const
311 status_t error
= (attribute
? B_OK
: B_BAD_VALUE
);
314 *attribute
= fAttributes
.First();
315 else if ((*attribute
)->GetNode() == this)
316 *attribute
= fAttributes
.GetNext(*attribute
);
319 if (error
== B_OK
&& !*attribute
)
320 error
= B_ENTRY_NOT_FOUND
;
327 Node::GetFirstReferrer() const
329 return fReferrers
.First();
334 Node::GetLastReferrer() const
336 return fReferrers
.Last();
339 // GetPreviousReferrer
341 Node::GetPreviousReferrer(Entry
*entry
) const
343 return (entry
? fReferrers
.GetPrevious(entry
) : NULL
);
348 Node::GetNextReferrer(Entry
*entry
) const
350 return (entry
? fReferrers
.GetNext(entry
) : NULL
);
355 Node::GetAllocationInfo(AllocationInfo
&info
)
357 Attribute
*attribute
= NULL
;
358 while (GetNextAttribute(&attribute
) == B_OK
)
359 attribute
->GetAllocationInfo(info
);