[PATCH] Add substitutions %t, %j, and %J as path-safe variants of %T, %i, and %I.

Dr. Thomas Orgis thomas.orgis at uni-hamburg.de
Thu Nov 23 19:07:51 UTC 2017


Rationale: Using the existing substitutions in construction of paths
(dynamic shares, created on client connect) results in directory names with
colons and dots in them. Those can be hard to use when accessed from a
different share, as Windows does not allow : in paths and has some ideas about
dots.

Signed-off-by: Dr. Thomas Orgis <thomas.orgis at uni-hamburg.de>
---
 docs-xml/manpages/smb.conf.5.xml | 19 +++++++++++++++++++
 lib/util/time.c                  | 41 ++++++++++++++++++++++++++++++++++++++++
 lib/util/time.h                  | 15 +++++++++++++++
 source3/lib/substitute.c         | 32 +++++++++++++++++++++++++++++++
 4 files changed, 107 insertions(+)

diff --git a/docs-xml/manpages/smb.conf.5.xml b/docs-xml/manpages/smb.conf.5.xml
index 49928134f09..f732c308f64 100644
--- a/docs-xml/manpages/smb.conf.5.xml
+++ b/docs-xml/manpages/smb.conf.5.xml
@@ -509,6 +509,13 @@ chmod 1770 /usr/local/samba/lib/usershares
 		</listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>%J</term>
+		<listitem><para>the IP address of the client machine,
+			colons/dots replaced by underscores.</para>
+		</listitem>
+		</varlistentry>
+
 		<varlistentry>
 		<term>%i</term>
 		<listitem><para>the local IP address to which a client connected.</para>
@@ -517,11 +524,23 @@ chmod 1770 /usr/local/samba/lib/usershares
 		</listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>%j</term>
+		<listitem><para>the local IP address to which a client connected,
+			colons/dots replaced by underscores.</para>
+		</listitem>
+		</varlistentry>
+
 		<varlistentry>
 		<term>%T</term>
 		<listitem><para>the current date and time.</para></listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>%t</term>
+		<listitem><para>the current date and time in a minimal format without colons (YYYYYmmdd_HHMMSS).</para></listitem>
+		</varlistentry>
+
 		<varlistentry>
 		<term>%D</term>
 		<listitem><para>name of the domain or workgroup of the current user.</para></listitem>
diff --git a/lib/util/time.c b/lib/util/time.c
index 8a4d93d4ac1..9880cff0be0 100644
--- a/lib/util/time.c
+++ b/lib/util/time.c
@@ -367,6 +367,47 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires)
 	return timeval_string(ctx, &tv, hires);
 }
 
+/**
+ Return date and time as a minimal string avoiding funny characters
+ that may cause trouble in file names. We only use digits and
+ underscore ... or a minus/hyphen if we got negative time.
+**/
+char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
+{
+	time_t t;
+	struct tm *tm;
+
+	t = (time_t)tp->tv_sec;
+	tm = localtime(&t);
+	if (!tm) {
+		if (hires) {
+			return talloc_asprintf(ctx, "%ld_%06ld",
+					       (long)tp->tv_sec,
+					       (long)tp->tv_usec);
+		} else {
+			return talloc_asprintf(ctx, "%ld", (long)t);
+		}
+	} else {
+		if (hires) {
+			return talloc_asprintf(ctx, "%04d%02d%02d_%02d%02d%02d_%06ld",
+					       tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+					       tm->tm_hour, tm->tm_min, tm->tm_sec,
+					       (long)tp->tv_usec);
+		} else {
+			return talloc_asprintf(ctx, "%04d%02d%02d_%02d%02d%02d",
+					       tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+					       tm->tm_hour, tm->tm_min, tm->tm_sec);
+		}
+	}
+}
+
+char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires)
+{
+	struct timeval tv;
+
+	GetTimeOfDay(&tv);
+	return minimal_timeval_string(ctx, &tv, hires);
+}
 
 /**
 return a HTTP/1.0 time string
diff --git a/lib/util/time.h b/lib/util/time.h
index 42d23865b82..9b897eb4b6c 100644
--- a/lib/util/time.h
+++ b/lib/util/time.h
@@ -138,6 +138,21 @@ char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires);
 **/
 char *current_timestring(TALLOC_CTX *ctx, bool hires);
 
+/**
+ Return a date and time as a string (optionally with microseconds)
+
+ format is %Y%m%d_%H%M%S or %Y%m%d_%H%M%S_%us
+**/
+
+char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires);
+
+/**
+ Return the current date and time as a string (optionally with microseconds)
+
+ format is %Y%m%d_%H%M%S or %Y%m%d_%H%M%S_%us
+**/
+char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires);
+
 /**
 return a HTTP/1.0 time string
 **/
diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c
index bc34c317974..9fdc5ca1edc 100644
--- a/source3/lib/substitute.c
+++ b/source3/lib/substitute.c
@@ -454,6 +454,20 @@ void standard_sub_basic(const char *smb_name, const char *domain_name,
 	TALLOC_FREE( s );
 }
 
+/*
+ * Limit addresses to hexalpha charactes and underscore, safe for path
+ * components for Windows clients.
+ */
+static void make_address_pathsafe(char *addr)
+{
+	while(addr && *addr) {
+		if(!isxdigit(*addr)) {
+			*addr = '_';
+		}
+		++addr;
+	}
+}
+
 /****************************************************************************
  Do some standard substitutions in a string.
  This function will return a talloced string that has to be freed.
@@ -550,11 +564,25 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx,
 				sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0");
 			break;
 		}
+		case 'J' : {
+			r = talloc_strdup(tmp_ctx,
+				sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0");
+			make_address_pathsafe(r);
+			a_string = realloc_string_sub(a_string, "%J", r);
+			break;
+		}
 		case 'i': 
 			a_string = realloc_string_sub(
 				a_string, "%i",
 				sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0");
 			break;
+		case 'j' : {
+			r = talloc_strdup(tmp_ctx,
+				sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0");
+			make_address_pathsafe(r);
+			a_string = realloc_string_sub(a_string, "%j", r);
+			break;
+		}
 		case 'L' : 
 			if ( strncasecmp_m(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
 				break;
@@ -578,6 +606,10 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx,
 		case 'T' :
 			a_string = realloc_string_sub(a_string, "%T", current_timestring(tmp_ctx, False));
 			break;
+		case 't' :
+			a_string = realloc_string_sub(a_string, "%t",
+						      current_minimal_timestring(tmp_ctx, False));
+			break;
 		case 'a' :
 			a_string = realloc_string_sub(a_string, "%a",
 					get_remote_arch_str());
-- 
2.15.0




More information about the samba-technical mailing list