git

Форк
0
/
unix-socket.c 
137 строк · 2.8 Кб
1
#include "git-compat-util.h"
2
#include "strbuf.h"
3
#include "unix-socket.h"
4

5
#define DEFAULT_UNIX_STREAM_LISTEN_BACKLOG (5)
6

7
static int chdir_len(const char *orig, int len)
8
{
9
	char *path = xmemdupz(orig, len);
10
	int r = chdir(path);
11
	free(path);
12
	return r;
13
}
14

15
struct unix_sockaddr_context {
16
	char *orig_dir;
17
};
18

19
static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
20
{
21
	if (!ctx->orig_dir)
22
		return;
23
	/*
24
	 * If we fail, we can't just return an error, since we have
25
	 * moved the cwd of the whole process, which could confuse calling
26
	 * code.  We are better off to just die.
27
	 */
28
	if (chdir(ctx->orig_dir) < 0)
29
		die("unable to restore original working directory");
30
	free(ctx->orig_dir);
31
}
32

33
static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
34
			      struct unix_sockaddr_context *ctx,
35
			      int disallow_chdir)
36
{
37
	int size = strlen(path) + 1;
38

39
	ctx->orig_dir = NULL;
40
	if (size > sizeof(sa->sun_path)) {
41
		const char *slash;
42
		const char *dir;
43
		struct strbuf cwd = STRBUF_INIT;
44

45
		if (disallow_chdir) {
46
			errno = ENAMETOOLONG;
47
			return -1;
48
		}
49

50
		slash = find_last_dir_sep(path);
51
		if (!slash) {
52
			errno = ENAMETOOLONG;
53
			return -1;
54
		}
55

56
		dir = path;
57
		path = slash + 1;
58
		size = strlen(path) + 1;
59
		if (size > sizeof(sa->sun_path)) {
60
			errno = ENAMETOOLONG;
61
			return -1;
62
		}
63
		if (strbuf_getcwd(&cwd))
64
			return -1;
65
		ctx->orig_dir = strbuf_detach(&cwd, NULL);
66
		if (chdir_len(dir, slash - dir) < 0)
67
			return -1;
68
	}
69

70
	memset(sa, 0, sizeof(*sa));
71
	sa->sun_family = AF_UNIX;
72
	memcpy(sa->sun_path, path, size);
73
	return 0;
74
}
75

76
int unix_stream_connect(const char *path, int disallow_chdir)
77
{
78
	int fd = -1, saved_errno;
79
	struct sockaddr_un sa;
80
	struct unix_sockaddr_context ctx;
81

82
	if (unix_sockaddr_init(&sa, path, &ctx, disallow_chdir) < 0)
83
		return -1;
84
	fd = socket(AF_UNIX, SOCK_STREAM, 0);
85
	if (fd < 0)
86
		goto fail;
87

88
	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
89
		goto fail;
90
	unix_sockaddr_cleanup(&ctx);
91
	return fd;
92

93
fail:
94
	saved_errno = errno;
95
	if (fd != -1)
96
		close(fd);
97
	unix_sockaddr_cleanup(&ctx);
98
	errno = saved_errno;
99
	return -1;
100
}
101

102
int unix_stream_listen(const char *path,
103
		       const struct unix_stream_listen_opts *opts)
104
{
105
	int fd = -1, saved_errno;
106
	int backlog;
107
	struct sockaddr_un sa;
108
	struct unix_sockaddr_context ctx;
109

110
	unlink(path);
111

112
	if (unix_sockaddr_init(&sa, path, &ctx, opts->disallow_chdir) < 0)
113
		return -1;
114
	fd = socket(AF_UNIX, SOCK_STREAM, 0);
115
	if (fd < 0)
116
		goto fail;
117

118
	if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
119
		goto fail;
120

121
	backlog = opts->listen_backlog_size;
122
	if (backlog <= 0)
123
		backlog = DEFAULT_UNIX_STREAM_LISTEN_BACKLOG;
124
	if (listen(fd, backlog) < 0)
125
		goto fail;
126

127
	unix_sockaddr_cleanup(&ctx);
128
	return fd;
129

130
fail:
131
	saved_errno = errno;
132
	if (fd != -1)
133
		close(fd);
134
	unix_sockaddr_cleanup(&ctx);
135
	errno = saved_errno;
136
	return -1;
137
}
138

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.