2 #include "unix-socket.h"
4 #define DEFAULT_UNIX_STREAM_LISTEN_BACKLOG (5)
6 static int chdir_len(const char *orig
, int len
)
8 char *path
= xmemdupz(orig
, len
);
14 struct unix_sockaddr_context
{
18 static void unix_sockaddr_cleanup(struct unix_sockaddr_context
*ctx
)
23 * If we fail, we can't just return an error, since we have
24 * moved the cwd of the whole process, which could confuse calling
25 * code. We are better off to just die.
27 if (chdir(ctx
->orig_dir
) < 0)
28 die("unable to restore original working directory");
32 static int unix_sockaddr_init(struct sockaddr_un
*sa
, const char *path
,
33 struct unix_sockaddr_context
*ctx
,
36 int size
= strlen(path
) + 1;
39 if (size
> sizeof(sa
->sun_path
)) {
42 struct strbuf cwd
= STRBUF_INIT
;
49 slash
= find_last_dir_sep(path
);
57 size
= strlen(path
) + 1;
58 if (size
> sizeof(sa
->sun_path
)) {
62 if (strbuf_getcwd(&cwd
))
64 ctx
->orig_dir
= strbuf_detach(&cwd
, NULL
);
65 if (chdir_len(dir
, slash
- dir
) < 0)
69 memset(sa
, 0, sizeof(*sa
));
70 sa
->sun_family
= AF_UNIX
;
71 memcpy(sa
->sun_path
, path
, size
);
75 int unix_stream_connect(const char *path
, int disallow_chdir
)
77 int fd
= -1, saved_errno
;
78 struct sockaddr_un sa
;
79 struct unix_sockaddr_context ctx
;
81 if (unix_sockaddr_init(&sa
, path
, &ctx
, disallow_chdir
) < 0)
83 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
87 if (connect(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0)
89 unix_sockaddr_cleanup(&ctx
);
96 unix_sockaddr_cleanup(&ctx
);
101 int unix_stream_listen(const char *path
,
102 const struct unix_stream_listen_opts
*opts
)
104 int fd
= -1, saved_errno
;
106 struct sockaddr_un sa
;
107 struct unix_sockaddr_context ctx
;
111 if (unix_sockaddr_init(&sa
, path
, &ctx
, opts
->disallow_chdir
) < 0)
113 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
117 if (bind(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0)
120 backlog
= opts
->listen_backlog_size
;
122 backlog
= DEFAULT_UNIX_STREAM_LISTEN_BACKLOG
;
123 if (listen(fd
, backlog
) < 0)
126 unix_sockaddr_cleanup(&ctx
);
133 unix_sockaddr_cleanup(&ctx
);