subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1381257 - /subversion/trunk/subversion/libsvn_subr/sysinfo.c
Date Wed, 05 Sep 2012 17:20:00 GMT
Author: brane
Date: Wed Sep  5 17:19:59 2012
New Revision: 1381257

URL: http://svn.apache.org/viewvc?rev=1381257&view=rev
Log:
Try to find the Linux release name for "svn --version --verbose".

* subversion/libsvn_subr/sysinfo.c: Include apr_signal.h, apr_thread_proc.h,
  svn_io.h and svn_string.h.
  (linux_release_name, read_file_contents, stringbuf_split_key,
   stringbuf_first_line_only, lsb_release, redhat_release,
   suse_release, debian_release): New.
  (svn_sysinfo__release_name): Use linux_release_name on Linux.

Modified:
    subversion/trunk/subversion/libsvn_subr/sysinfo.c

Modified: subversion/trunk/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sysinfo.c?rev=1381257&r1=1381256&r2=1381257&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/sysinfo.c Wed Sep  5 17:19:59 2012
@@ -36,12 +36,16 @@
 #include <apr_lib.h>
 #include <apr_pools.h>
 #include <apr_file_info.h>
+#include <apr_signal.h>
 #include <apr_strings.h>
+#include <apr_thread_proc.h>
 #include <apr_version.h>
 #include <apu_version.h>
 
 #include "svn_ctype.h"
 #include "svn_error.h"
+#include "svn_io.h"
+#include "svn_string.h"
 #include "svn_utf.h"
 
 #include "private/svn_sqlite.h"
@@ -74,6 +78,9 @@ static const apr_array_header_t *win32_s
 static const char *macos_release_name(apr_pool_t *pool);
 #endif  /* SVN_HAVE_MACOS_PLIST */
 
+#if LINUX
+static const char *linux_release_name(apr_pool_t *pool);
+#endif
 
 const char *
 svn_sysinfo__canonical_host(apr_pool_t *pool)
@@ -93,8 +100,10 @@ svn_sysinfo__release_name(apr_pool_t *po
 {
 #ifdef WIN32
   return win32_release_name(pool);
-#elif SVN_HAVE_MACOS_PLIST
+#elif defined(SVN_HAVE_MACOS_PLIST)
   return macos_release_name(pool);
+#elif LINUX
+  return linux_release_name(pool);
 #elif HAVE_UNAME
   return release_name_from_uname(pool);
 #else
@@ -205,7 +214,7 @@ canonical_host_from_uname(apr_pool_t *po
   return apr_psprintf(pool, "%s-%s-%s%s", machine, vendor, sysname, sysver);
 }
 
-# if !SVN_HAVE_MACOS_PLIST
+# ifndef SVN_HAVE_MACOS_PLIST
 /* Generate a release name from the uname(3) info, effectively
    returning "`uname -s` `uname -r`". */
 static const char *
@@ -247,6 +256,273 @@ release_name_from_uname(apr_pool_t *pool
 #endif  /* HAVE_UNAME */
 
 
+#if LINUX
+/* Split a stringbuf into a key/value pair.
+   Return the key, leaving the striped value in the stringbuf. */
+static const char *
+stringbuf_split_key(svn_stringbuf_t *buffer, char delim)
+{
+  char *key;
+  char *end;
+
+  end = strchr(buffer->data, delim);
+  if (!end)
+    return NULL;
+
+  svn_stringbuf_strip_whitespace(buffer);
+  key = buffer->data;
+  end = strchr(key, delim);
+  *end = '\0';
+  buffer->len = 1 + end - key;
+  buffer->data = end + 1;
+  svn_stringbuf_strip_whitespace(buffer);
+
+  return key;
+}
+
+/* Parse `/usr/bin/lsb_rlease --all` */
+static const char *
+lsb_release(apr_pool_t *pool)
+{
+  static const char *const args[3] =
+    {
+      "/usr/bin/lsb_release",
+      "--all",
+      NULL
+    };
+
+  const char *distributor = NULL;
+  const char *description = NULL;
+  const char *release = NULL;
+  const char *codename = NULL;
+
+  apr_proc_t lsbproc;
+  svn_stream_t *lsbinfo;
+  svn_error_t *err;
+
+  /* Run /usr/bin/lsb_release --all < /dev/null 2>/dev/null */
+  {
+    apr_file_t *stdin_handle;
+    apr_file_t *stdout_handle;
+
+    err = svn_io_file_open(&stdin_handle, SVN_NULL_DEVICE_NAME,
+                           APR_READ, APR_OS_DEFAULT, pool);
+    if (!err)
+      err = svn_io_file_open(&stdout_handle, SVN_NULL_DEVICE_NAME,
+                             APR_WRITE, APR_OS_DEFAULT, pool);
+    if (!err)
+      err = svn_io_start_cmd3(&lsbproc, NULL, args[0], args, NULL, FALSE,
+                              FALSE, stdin_handle,
+                              TRUE, NULL,
+                              FALSE, stdout_handle,
+                              pool);
+    if (err)
+      {
+        svn_error_clear(err);
+        return NULL;
+      }
+  }
+
+  /* Parse the output and try to populate the  */
+  lsbinfo = svn_stream_from_aprfile2(lsbproc.out, TRUE, pool);
+  if (lsbinfo)
+    {
+      for (;;)
+        {
+          svn_boolean_t eof = FALSE;
+          svn_stringbuf_t *line;
+          const char *key;
+
+          err = svn_stream_readline(lsbinfo, &line, "\n", &eof, pool);
+          if (err || eof)
+            break;
+
+          key = stringbuf_split_key(line, ':');
+          if (!key)
+            continue;
+
+          if (0 == svn_cstring_casecmp(key, "Distributor ID"))
+            distributor = line->data;
+          else if (0 == svn_cstring_casecmp(key, "Description"))
+            description = line->data;
+          else if (0 == svn_cstring_casecmp(key, "Release"))
+            release = line->data;
+          else if (0 == svn_cstring_casecmp(key, "Codename"))
+            codename = line->data;
+        }
+      svn_stream_close(lsbinfo);
+      if (err)
+        {
+          svn_error_clear(err);
+          apr_proc_kill(&lsbproc, SIGKILL);
+          return NULL;
+        }
+    }
+
+  /* Reap the child process */
+  err = svn_io_wait_for_cmd(&lsbproc, "", NULL, NULL, pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return NULL;
+    }
+
+  if (description)
+    return apr_psprintf(pool, "%s%s%s%s", description,
+                        (codename ? " (" : ""),
+                        (codename ? codename : ""),
+                        (codename ? ")" : ""));
+  if (distributor)
+    return apr_psprintf(pool, "%s%s%s%s%s%s", distributor,
+                        (release ? " " : ""),
+                        (release ? release : ""),
+                        (codename ? " (" : ""),
+                        (codename ? codename : ""),
+                        (codename ? ")" : ""));
+
+  return NULL;
+}
+
+/* Read the whole contents of a file. */
+static svn_stringbuf_t *
+read_file_contents(const char *filename, apr_pool_t *pool)
+{
+  svn_error_t *err;
+  svn_stringbuf_t *buffer;
+
+  err = svn_stringbuf_from_file2(&buffer, filename, pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return NULL;
+    }
+
+  return buffer;
+}
+
+/* Strip everything but the first line from a stringbuf. */
+static void
+stringbuf_first_line_only(svn_stringbuf_t *buffer)
+{
+  char *eol = strchr(buffer->data, '\n');
+  if (eol)
+    {
+      *eol = '\0';
+      buffer->len = 1 + eol - buffer->data;
+    }
+  svn_stringbuf_strip_whitespace(buffer);
+}
+
+/* Look at /etc/redhat_release to detect RHEL/Fedora/CentOS. */
+static const char *
+redhat_release(apr_pool_t *pool)
+{
+  svn_stringbuf_t *buffer = read_file_contents("/etc/redhat-release", pool);
+  if (buffer)
+    {
+      stringbuf_first_line_only(buffer);
+      return buffer->data;
+    }
+  return NULL;
+}
+
+/* Look at /etc/SuSE-release to detect non-LSB SuSE. */
+static const char *
+suse_release(apr_pool_t *pool)
+{
+  const char *release = NULL;
+  const char *codename = NULL;
+
+  svn_stringbuf_t *buffer = read_file_contents("/etc/SuSE-release", pool);
+  svn_stringbuf_t *line;
+  svn_stream_t *stream;
+  svn_boolean_t eof;
+  svn_error_t *err;
+  if (!buffer)
+      return NULL;
+
+  stream = svn_stream_from_stringbuf(buffer, pool);
+  err = svn_stream_readline(stream, &line, "\n", &eof, pool);
+  if (err || eof)
+    {
+      svn_error_clear(err);
+      return NULL;
+    }
+
+  svn_stringbuf_strip_whitespace(line);
+  release = line->data;
+
+  for (;;)
+    {
+      const char *key;
+
+      err = svn_stream_readline(stream, &line, "\n", &eof, pool);
+      if (err || eof)
+        {
+          svn_error_clear(err);
+          break;
+        }
+
+      key = stringbuf_split_key(line, '=');
+      if (!key)
+        continue;
+
+      if (0 == strncmp(key, "CODENAME", 8))
+        codename = line->data;
+    }
+
+  return apr_psprintf(pool, "%s%s%s%s",
+                      release,
+                      (codename ? " (" : ""),
+                      (codename ? codename : ""),
+                      (codename ? ")" : ""));
+}
+
+/* Look at /etc/debian_version to detect non-LSB Debian. */
+static const char *
+debian_release(apr_pool_t *pool)
+{
+  svn_stringbuf_t *buffer = read_file_contents("/etc/debian_version", pool);
+  if (!buffer)
+      return NULL;
+
+  stringbuf_first_line_only(buffer);
+  return apr_pstrcat(pool, "Debian ", buffer->data, NULL);
+}
+
+/* Try to find the Linux distribution name, or return info from uname. */
+static const char *
+linux_release_name(apr_pool_t *pool)
+{
+  const char *uname_release = release_name_from_uname(pool);
+
+  /* Try anything that has /usr/bin/lsb_release.
+     Covers, for example, Debian, Ubuntu and SuSE.  */
+  const char *release_name = lsb_release(pool);
+
+  /* Try RHEL/Fedora/CentOS */
+  if (!release_name)
+    release_name = redhat_release(pool);
+
+  /* Try Non-LSB SuSE */
+  if (!release_name)
+    release_name = suse_release(pool);
+
+  /* Try non-LSB Debian */
+  if (!release_name)
+    release_name = debian_release(pool);
+
+  if (!release_name)
+    return uname_release;
+
+  if (!uname_release)
+    return release_name;
+
+  return apr_psprintf(pool, "%s [%s]", release_name, uname_release);
+}
+#endif /* LINUX */
+
+
 #ifdef WIN32
 typedef DWORD (WINAPI *FNGETNATIVESYSTEMINFO)(LPSYSTEM_INFO);
 typedef BOOL (WINAPI *FNENUMPROCESSMODULES) (HANDLE, HMODULE, DWORD, LPDWORD);



Mime
View raw message