[PATCH 10 of 14] chg: calculate sockdirfd
Jun Wu
quark at fb.com
Sun Apr 10 19:57:27 EDT 2016
# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1460330280 -3600
# Mon Apr 11 00:18:00 2016 +0100
# Node ID 1b8ee8aabe42b44cd865d41bf095c2cf7892e4dc
# Parent 68977496c0f5b4026c19cd8ec4ea22113401c030
chg: calculate sockdirfd
This is a part of the series to support long socket path. Before this patch,
sockdirfd is AT_FDCWD, making it effectively unused. This patch calculates
sockdirfd and makes sockname and lockfile basenames instead of full paths.
diff --git a/contrib/chg/chg.c b/contrib/chg/chg.c
--- a/contrib/chg/chg.c
+++ b/contrib/chg/chg.c
@@ -29,6 +29,10 @@
#define UNIX_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path))
#endif
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
struct cmdserveropts {
char sockname[UNIX_PATH_MAX];
char redirectsockname[UNIX_PATH_MAX];
@@ -140,8 +144,9 @@
static void setcmdserveropts(struct cmdserveropts *opts)
{
int r;
- char sockdir[UNIX_PATH_MAX];
+ char sockdir[PATH_MAX];
const char *envsockname = getenv("CHGSOCKNAME");
+ const char *basename = NULL;
if (!envsockname) {
/* by default, put socket file in secure directory
* (permission of socket file may be ignored on some Unices) */
@@ -153,14 +158,38 @@
if (r < 0 || (size_t)r >= sizeof(sockdir))
abortmsg("too long TMPDIR (r = %d)", r);
preparesockdir(sockdir);
+ basename = "server";
+ } else {
+ /* otherwise, split the path the user provides */
+ const char *lastsep = strrchr(envsockname, '/');
+ if (lastsep) {
+ size_t len = lastsep - envsockname + 1;
+ if (len >= sizeof(sockdir))
+ abortmsg("CHGSOCKNAME is too long");
+ memcpy(sockdir, envsockname, len);
+ sockdir[len] = '\0';
+ basename = lastsep + 1;
+ } else {
+ r = snprintf(sockdir, sizeof(sockdir), ".");
+ assert(r == 2);
+ basename = envsockname;
+ }
}
- const char *basename = (envsockname) ? envsockname : sockdir;
- const char *sockfmt = (envsockname) ? "%s" : "%s/server";
- const char *lockfmt = (envsockname) ? "%s.lock" : "%s/lock";
- r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
- if (r < 0 || (size_t)r >= sizeof(opts->sockname))
- abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
+ if (basename[0] == '\0')
+ abortmsg("basename cannot be empty");
+
+ opts->sockdirfd = open(sockdir, O_DIRECTORY);
+ if (opts->sockdirfd == -1)
+ abortmsgerrno("failed to open dir %s", sockdir);
+ fsetcloexec(opts->sockdirfd);
+
+ opts->sockname[sizeof(opts->sockname) - 1] = '\0';
+ strncpy(opts->sockname, basename, sizeof(opts->sockname));
+ if (opts->sockname[sizeof(opts->sockname) - 1] != '\0')
+ abortmsg("basename %s is too long", basename);
+
+ static const char lockfmt[] = "%s.lock";
r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename);
if (r < 0 || (size_t)r >= sizeof(opts->lockfile))
abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
More information about the Mercurial-devel
mailing list