@@ -48,15 +48,15 @@ namespace vfs::socket
4848 std::size_t off, std::size_t len, bool &fault
4949 );
5050
51- // TODO: scm rights, abstract namespace, connected dgram, msg_more, cmsg_cloexec, trunc
51+ // TODO: scm rights, connected dgram, msg_more, cmsg_cloexec, trunc
5252
53- // struct unix_sock;
54- // lib::locker<
55- // lib::map::flat_hash<
56- // std::string,
57- // std::weak_ptr<unix_sock>
58- // >, sched::mutex
59- // > abstract;
53+ struct unix_sock ;
54+ lib::locker<
55+ lib::map::flat_hash<
56+ std::string,
57+ std::weak_ptr<unix_sock>
58+ >, sched::mutex
59+ > abstract;
6060
6161 enum state { unconnected, connecting, connected, listening, disconnecting };
6262 struct unix_sock : socket_t , std::enable_shared_from_this<unix_sock>
@@ -146,23 +146,28 @@ namespace vfs::socket
146146 if (addr.size () < sizeof (addr_fam) || addr.size () > sizeof (sockaddr_un))
147147 return std::unexpected { lib::err::invalid_argument };
148148
149- sockaddr_un sa;
150- addr.copy_to (std::as_writable_bytes (std::span { &sa, 1 }));
149+ sockaddr_un sa { } ;
150+ addr.copy_to (std::as_writable_bytes (std::span { &sa, 1 }). subspan ( 0 , addr. size ()) );
151151
152152 if (sa.sun_family != af_unix)
153153 return std::unexpected { lib::err::address_family_unsupported };
154154
155155 std::string_view path;
156+ bool is_abstract = false ;
157+
156158 if (addr.size () > sizeof (addr_fam))
157159 {
160+ const auto max_len = addr.size () - sizeof (addr_fam);
158161 if (sa.sun_path [0 ] == 0 )
159162 {
160- // TODO
161- return std::unexpected { lib::err::not_supported };
163+ is_abstract = true ;
164+ path = std::string_view { sa.sun_path , max_len };
165+ }
166+ else
167+ {
168+ const auto len = std::strnlen (sa.sun_path , max_len);
169+ path = std::string_view { sa.sun_path , len };
162170 }
163-
164- const auto len = std::strnlen (sa.sun_path , addr.size () - sizeof (addr_fam));
165- path = std::string_view { sa.sun_path , len };
166171 }
167172 else path = " " ;
168173
@@ -173,6 +178,18 @@ namespace vfs::socket
173178 if (slocked->state != unconnected)
174179 return std::unexpected { lib::err::invalid_argument };
175180
181+ if (is_abstract)
182+ {
183+ auto registry = abstract.lock ();
184+ if (registry->contains (path))
185+ return std::unexpected { lib::err::address_in_use };
186+
187+ registry->insert ({ std::string { path }, shared_from_this () });
188+ slocked->bound_path = path;
189+
190+ return { };
191+ }
192+
176193 const auto proc = sched::current_process ();
177194 const auto ret = vfs::create (
178195 proc->vfs ->cwd , path, (0777 & ~proc->vfs ->umask ) | stat::s_ifsock, 0
@@ -197,32 +214,56 @@ namespace vfs::socket
197214 return std::unexpected { lib::err::invalid_argument };
198215
199216 sockaddr_un sa { };
200- addr.copy_to (std::as_writable_bytes (std::span { &sa, 1 }));
217+ addr.copy_to (std::as_writable_bytes (std::span { &sa, 1 }). subspan ( 0 , addr. size ()) );
201218
202219 if (sa.sun_family != af_unix)
203220 return std::unexpected { lib::err::address_family_unsupported };
204221
205222 std::string_view path;
223+ bool is_abstract = false ;
224+
206225 if (addr.size () > sizeof (addr_fam))
207226 {
227+ const auto max_len = addr.size () - sizeof (addr_fam);
208228 if (sa.sun_path [0 ] == 0 )
209- return std::unexpected { lib::err::not_found };
210-
211- const auto len = std::strnlen (sa.sun_path , addr.size () - sizeof (addr_fam));
212- path = std::string_view { sa.sun_path , len };
229+ {
230+ is_abstract = true ;
231+ path = std::string_view { sa.sun_path , max_len };
232+ }
233+ else
234+ {
235+ const auto len = std::strnlen (sa.sun_path , max_len);
236+ path = std::string_view { sa.sun_path , len };
237+ }
213238 }
214239 else return std::unexpected { lib::err::not_found };
215240
216241 const auto proc = sched::current_process ();
217- const auto res = vfs::resolve (proc->vfs ->cwd , path);
218- if (!res)
219- return std::unexpected { res.error () };
242+ std::shared_ptr<unix_sock> target;
220243
221- auto &inode = res->target .dentry ->inode ;
222- if (inode->stat .type () != stat::s_ifsock)
223- return std::unexpected { lib::err::connection_refused };
244+ if (is_abstract)
245+ {
246+ auto registry = abstract.lock ();
247+ auto it = registry->find (path);
248+ if (it == registry->end ())
249+ return std::unexpected { lib::err::connection_refused };
224250
225- auto target = private_t::get (inode)->sock .lock ();
251+ target = it->second .lock ();
252+ if (!target)
253+ return std::unexpected { lib::err::connection_refused };
254+ }
255+ else
256+ {
257+ const auto res = vfs::resolve (proc->vfs ->cwd , path);
258+ if (!res)
259+ return std::unexpected { res.error () };
260+
261+ auto &inode = res->target .dentry ->inode ;
262+ if (inode->stat .type () != stat::s_ifsock)
263+ return std::unexpected { lib::err::connection_refused };
264+
265+ target = private_t::get (inode)->sock .lock ();
266+ }
226267 if (!target)
227268 return std::unexpected { lib::err::connection_refused };
228269
@@ -339,12 +380,14 @@ namespace vfs::socket
339380 auto pslocked = connecting->state .lock ();
340381 if (!pslocked->bound_path .empty ())
341382 {
342- std::strncpy (
343- sa.sun_path ,
344- pslocked->bound_path .c_str (),
345- sizeof (sa.sun_path ) - 1
383+ const bool is_abstract = pslocked->bound_path [0 ] == 0 ;
384+ const auto copy_size = std::min (
385+ pslocked->bound_path .size (), sizeof (sa.sun_path )
346386 );
347- actual = sizeof (addr_fam) + pslocked->bound_path .size () + 1 ;
387+
388+ std::memcpy (sa.sun_path , pslocked->bound_path .data (), copy_size);
389+ actual = static_cast <socklen_t >(sizeof (addr_fam) +
390+ pslocked->bound_path .size () + !is_abstract);
348391 }
349392 }
350393
@@ -495,26 +538,44 @@ namespace vfs::socket
495538 if (!hdr.name .empty ())
496539 {
497540 sockaddr_un sa { };
498- hdr.name .copy_to (std::as_writable_bytes (std::span { &sa, 1 }));
541+ hdr.name .copy_to (std::as_writable_bytes (std::span { &sa, 1 })
542+ .subspan (0 , hdr.name .size ()));
543+
499544 if (sa.sun_family != af_unix)
500545 return std::unexpected { lib::err::address_family_unsupported };
501546
502- const auto len = std::strnlen (
503- sa.sun_path ,
504- hdr.name .size () - sizeof (addr_fam)
505- );
506- const std::string_view path { sa.sun_path , len };
547+ const auto max_len = hdr.name .size () - sizeof (addr_fam);
548+ if (max_len == 0 )
549+ return std::unexpected { lib::err::invalid_argument };
507550
508- const auto proc = sched::current_process ();
509- const auto res = vfs::resolve (proc->vfs ->cwd , path);
510- if (!res)
511- return std::unexpected { res.error () };
551+ if (sa.sun_path [0 ] == ' \0 ' )
552+ {
553+ const std::string_view path { sa.sun_path , max_len };
512554
513- auto &inode = res->target .dentry ->inode ;
514- if (inode->stat .type () != stat::s_ifsock)
515- return std::unexpected { lib::err::connection_refused };
555+ auto registry = abstract.lock ();
556+ auto it = registry->find (path);
557+ if (it == registry->end ())
558+ return std::unexpected { lib::err::connection_refused };
559+
560+ dest = it->second .lock ();
561+ }
562+ else
563+ {
564+ const auto len = std::strnlen (sa.sun_path , max_len);
565+ const std::string_view path { sa.sun_path , len };
566+
567+ const auto proc = sched::current_process ();
568+ const auto res = vfs::resolve (proc->vfs ->cwd , path);
569+ if (!res)
570+ return std::unexpected { res.error () };
571+
572+ auto &inode = res->target .dentry ->inode ;
573+ if (inode->stat .type () != stat::s_ifsock)
574+ return std::unexpected { lib::err::connection_refused };
575+
576+ dest = private_t::get (inode)->sock .lock ();
577+ }
516578
517- dest = private_t::get (inode)->sock .lock ();
518579 if (!dest)
519580 return std::unexpected { lib::err::connection_refused };
520581 }
@@ -743,13 +804,15 @@ namespace vfs::socket
743804 {
744805 sockaddr_un sa { };
745806 sa.sun_family = af_unix;
746- std::strncpy (
747- sa. sun_path ,
748- msg-> sender_path . c_str (),
749- sizeof (sa.sun_path ) - 1
807+
808+ const bool is_abstract = msg-> sender_path [ 0 ] == 0 ;
809+ const auto copy_size = std::min (
810+ msg-> sender_path . size (), sizeof (sa.sun_path )
750811 );
812+ std::memcpy (sa.sun_path , msg->sender_path .data (), copy_size);
751813
752- const auto sa_len = sizeof (addr_fam) + msg->sender_path .size () + 1 ;
814+ const auto sa_len = sizeof (addr_fam) +
815+ msg->sender_path .size () + !is_abstract;
753816 const auto copy_len = std::min (hdr.name .size (), sa_len);
754817
755818 hdr.name .subspan (0 , copy_len).copy_from (
@@ -900,12 +963,15 @@ namespace vfs::socket
900963 auto slocked = state.lock ();
901964 if (!slocked->bound_path .empty ())
902965 {
903- std::strncpy (
904- sa. sun_path ,
905- slocked->bound_path .c_str (),
906- sizeof (sa.sun_path ) - 1
966+ const bool is_abstract = slocked-> bound_path [ 0 ] == 0 ;
967+ const auto copy_size = std::min (
968+ slocked->bound_path .size (),
969+ sizeof (sa.sun_path )
907970 );
908- actual = sizeof (addr_fam) + slocked->bound_path .size () + 1 ;
971+ std::memcpy (sa.sun_path , slocked->bound_path .data (), copy_size);
972+
973+ actual = static_cast <socklen_t >(sizeof (addr_fam) +
974+ slocked->bound_path .size () + !is_abstract);
909975 }
910976 }
911977
@@ -1106,6 +1172,12 @@ namespace vfs::socket
11061172 {
11071173 {
11081174 auto slocked = state.lock ();
1175+ if (!slocked->bound_path .empty () && slocked->bound_path [0 ] == 0 )
1176+ {
1177+ auto registry = abstract.lock ();
1178+ registry->erase (slocked->bound_path );
1179+ }
1180+
11091181 slocked->state = disconnecting;
11101182 slocked->bound_inode .reset ();
11111183
0 commit comments