20 #include "UnixFilesystem.h" 21 #include "modules/subsys/posix/logging.h" 22 #include "pedigree/kernel/LockGuard.h" 23 #include "pedigree/kernel/process/Mutex.h" 24 #include "pedigree/kernel/process/Process.h" 25 #include "pedigree/kernel/process/Thread.h" 26 #include "pedigree/kernel/processor/Processor.h" 28 String UnixFilesystem::m_VolumeLabel(
"unix");
30 UnixSocket::UnixSocket(
33 :
File(name, 0, 0, 0, 0, pFs, 0, pParent), m_Type(type), m_State(Inactive),
34 m_Datagrams(MAX_UNIX_DGRAM_BACKLOG), m_pOther(other),
35 m_Stream(MAX_UNIX_STREAM_QUEUE), m_PendingSockets(), m_Mutex(false)
43 if (m_Type == Datagram)
57 if (m_Type == Streaming)
65 assert(m_pOther->m_pOther ==
this);
66 m_pOther->m_pOther =
nullptr;
67 m_pOther->m_State = Inactive;
72 if (getName().length() > 0)
81 if (m_Type == Streaming)
83 if (m_State == Inactive || m_State == Connecting)
90 if (m_pOther->m_Stream.canWrite(timeout == 1))
97 if (m_Stream.canRead(timeout == 1))
109 return m_Datagrams.waitFor(
110 bWriting ? RingBufferWait::Writing : RingBufferWait::Reading);
114 return m_Datagrams.canWrite();
118 return m_Datagrams.dataReady();
124 uint64_t location, uint64_t size, uintptr_t buffer,
bool bCanBlock)
127 return recvfrom(size, buffer, bCanBlock, remote);
130 uint64_t UnixSocket::recvfrom(
131 uint64_t size, uintptr_t buffer,
bool bCanBlock,
String &from)
133 if (m_State != Active)
137 N_NOTICE(
"UnixSocket::read => EOF (reading remainder of stream first)");
138 return m_Stream.read(reinterpret_cast<uint8_t *>(buffer), size,
false);
144 return m_Stream.read(
145 reinterpret_cast<uint8_t *>(buffer), size, bCanBlock);
150 if (!select(
false, 1))
155 else if (!select(
false, 0))
161 struct buf *b = m_Datagrams.read();
164 MemoryCopy(reinterpret_cast<void *>(buffer), b->pBuffer, size);
167 from = b->remotePath;
168 delete[] b->remotePath;
177 uint64_t location, uint64_t size, uintptr_t buffer,
bool bCanBlock)
179 if (m_State != Active)
182 N_NOTICE(
"UnixSocket::write => EOF");
188 return m_pOther->m_Stream.write(
189 reinterpret_cast<uint8_t *>(buffer), size, bCanBlock);
194 if (!select(
true, 1))
199 else if (!select(
true, 0))
205 struct buf *b =
new struct buf;
206 b->pBuffer =
new char[size];
207 MemoryCopy(b->pBuffer, reinterpret_cast<void *>(buffer), size);
212 b->remotePath =
new char[255];
213 StringCopyN(b->remotePath, reinterpret_cast<char *>(location), 255);
215 m_Datagrams.write(b);
222 bool UnixSocket::bind(
UnixSocket *other,
bool block)
226 ERROR(
"UnixSocket: trying to bind a socket that's already bound");
232 if (m_State != Inactive)
234 N_NOTICE(
"bind failed because this socket is already in a " 235 "non-inactive state");
242 if (m_pOther->m_State != Inactive)
244 N_NOTICE(
"bind failed because other socket is already in a " 245 "non-inactive state");
250 other->m_pOther =
this;
252 m_State = Connecting;
253 m_pOther->m_State = Connecting;
260 N_NOTICE(
"bind is not blocking, use poll() etc");
265 N_NOTICE(
"bind is waiting for an ack");
266 m_AckWaiter.acquire();
268 if (m_State != Active)
270 N_NOTICE(
"got ack but we're inactive");
274 N_NOTICE(
"got ack and we're now active");
280 void UnixSocket::unbind()
291 N_NOTICE(
"UnixSocket::unbind");
294 m_pOther->m_State = Closed;
297 m_AckWaiter.release();
298 m_pOther->m_AckWaiter.release();
301 if (m_Type == Streaming)
303 N_NOTICE(
"streaming notify eof");
306 m_Stream.notifyMonitors();
307 m_pOther->m_Stream.notifyMonitors();
311 void UnixSocket::acknowledgeBind()
322 if (m_State != Connecting || m_pOther->m_State != Connecting)
324 N_NOTICE(
"can't ack bind - one or both sockets are not connecting");
328 N_NOTICE(
"acking bind");
331 m_pOther->m_State = Active;
336 m_AckWaiter.release();
337 m_pOther->m_AckWaiter.release();
341 void UnixSocket::addSocket(
UnixSocket *socket)
345 if (m_State != Listening)
351 m_PendingSockets.pushBack(socket);
353 N_NOTICE(
"adding listening socket");
358 m_Stream.write(&c, 1);
363 if (m_State != Listening)
370 if (m_Stream.read(&c, 1, block) != 1)
375 N_NOTICE(
"got a socket");
379 N_NOTICE(
"popping & acking it");
381 UnixSocket *result = m_PendingSockets.popFront();
382 result->acknowledgeBind();
386 void UnixSocket::addWaiter(
Semaphore *waiter)
388 m_Stream.monitor(waiter);
391 m_pOther->m_Stream.monitor(waiter);
395 void UnixSocket::removeWaiter(
Semaphore *waiter)
397 m_Stream.cullMonitorTargets(waiter);
400 m_pOther->m_Stream.cullMonitorTargets(waiter);
404 void UnixSocket::addWaiter(
Thread *thread,
Event *event)
406 m_Stream.monitor(thread, event);
409 m_pOther->m_Stream.monitor(thread, event);
413 void UnixSocket::removeWaiter(
Event *event)
415 m_Stream.cullMonitorTargets(event);
418 m_pOther->m_Stream.cullMonitorTargets(event);
422 bool UnixSocket::markListening()
424 if (m_Type != Streaming)
430 if (m_State != Inactive)
440 void UnixSocket::setCreds()
445 m_Creds.uid = pCurrentProcess->
getUserId();
446 m_Creds.gid = pCurrentProcess->getGroupId();
447 m_Creds.pid = pCurrentProcess->
getId();
452 :
Directory(name, 0, 0, 0, 0, pFs, 0, pParent), m_Lock(
false)
454 cacheDirectoryContents();
457 UnixDirectory::~UnixDirectory()
461 bool UnixDirectory::addEntry(
String filename,
File *pFile)
464 addDirectoryEntry(filename, pFile);
468 bool UnixDirectory::removeEntry(
File *pFile)
473 remove(filename.
view());
479 markCachePopulated();
482 UnixFilesystem::UnixFilesystem() :
Filesystem(), m_pRoot(0)
485 pRoot->addEntry(
String(
"."), pRoot);
486 pRoot->addEntry(
String(
".."), pRoot);
491 m_pRoot->setPermissions(
492 FILE_UR | FILE_UW | FILE_UX | FILE_GR | FILE_GW | FILE_GX | FILE_OR |
496 UnixFilesystem::~UnixFilesystem()
502 File *parent,
const String &filename, uint32_t mask)
508 if (!pParent->addEntry(filename, pSocket))
515 pSocket->setPermissions(
516 FILE_UR | FILE_UW | FILE_UX | FILE_GR | FILE_GW | FILE_GX | FILE_OR |
523 File *parent,
const String &filename, uint32_t mask)
529 if (!pParent->addEntry(filename, pChild))
535 pChild->addEntry(
String(
"."), pChild);
536 pChild->addEntry(
String(
".."), pParent);
539 pChild->setPermissions(
540 FILE_UR | FILE_UW | FILE_UX | FILE_GR | FILE_GW | FILE_GX | FILE_OR |
550 return pParent->removeEntry(file);
virtual bool createDirectory(File *parent, const String &filename, uint32_t mask)
virtual bool createFile(File *parent, const String &filename, uint32_t mask)
virtual bool remove(File *parent, File *file)
static Directory * fromFile(File *pF)
virtual int64_t getUserId() const
static ProcessorInformation & information()
virtual void cacheDirectoryContents()
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
void remove(const HashedStringView &s)
virtual int select(bool bWriting=false, int timeout=0)