Ok, here is my patch proposition. I hope it's satisfactory.
Cheers
 Ondrej

----- Original Message -----
From: "Pádraig Brady" <p...@draigbrady.com>
To: "Ondrej Oprala" <oopr...@redhat.com>
Cc: coreutils@gnu.org, "D Yu Bolkhovityanov" <d.yu.bolkhovitya...@inp.nsk.su>
Sent: Wednesday, July 25, 2012 11:24:59 PM
Subject: Re: RFE: hash-type in sum utils

On 07/25/2012 02:23 PM, Ondrej Oprala wrote:
> How should the '--tag' switch treat binary files? Should it create something 
> like this:
> MD5 (*filename) = ........   ?

Good question.
I wouldn't tag the filenamem because to be unambiguous you'd
have to have a space before the filename in text (default) mode,
and that would impact the current support for BSD format checksums.

I'd be inclined to tag just before the checksum like:

MD5 (filename) = binary_checksum (default for files on dos)
 MD5 (filename) = text_checksum  (default for files elsewhere)

I.E. in binary mode just use BSD format,
and add the extra space when generating text format.
This has the advantage of being mostly backwards compatible.
I.E. the existing GNU *sum utils accept a space before "MD5",
and so newer GNU `*sum --tag` output would be --check able on older
and other checksum utils.  The only backwards compat edge case
is with `*sum --tag --text` on dos, which would only be
compat with the newer versions of the GNU *sum tools.
But that's fine IMHO.

Another thing to consider if generating BSD format output,
is file name escaping.
Perhaps we want to follow BSDs rules here too,
which seems to use just use \ and ^ within the (filename brackets).
Doing that would allow use to be fully compat with their checksums and
also avoid the awkward backslash at start of line mode GNU currently uses,
which is not compatible with BSD format processing.

cheers,
Pádraig.
diff -up coreutils-8.17/src/md5sum.c.prefix coreutils-8.17/src/md5sum.c
--- coreutils-8.17/src/md5sum.c.prefix	2012-07-24 11:25:07.132521741 +0200
+++ coreutils-8.17/src/md5sum.c	2012-07-26 12:57:08.173864973 +0200
@@ -48,6 +48,7 @@
 # define DIGEST_BITS 128
 # define DIGEST_REFERENCE "RFC 1321"
 # define DIGEST_ALIGN 4
+# define PREFIX_INDEX 0
 #elif HASH_ALGO_SHA1
 # define PROGRAM_NAME "sha1sum"
 # define DIGEST_TYPE_STRING "SHA1"
@@ -55,6 +56,7 @@
 # define DIGEST_BITS 160
 # define DIGEST_REFERENCE "FIPS-180-1"
 # define DIGEST_ALIGN 4
+# define PREFIX_INDEX 1
 #elif HASH_ALGO_SHA256
 # define PROGRAM_NAME "sha256sum"
 # define DIGEST_TYPE_STRING "SHA256"
@@ -62,6 +64,7 @@
 # define DIGEST_BITS 256
 # define DIGEST_REFERENCE "FIPS-180-2"
 # define DIGEST_ALIGN 4
+# define PREFIX_INDEX 2
 #elif HASH_ALGO_SHA224
 # define PROGRAM_NAME "sha224sum"
 # define DIGEST_TYPE_STRING "SHA224"
@@ -69,6 +72,7 @@
 # define DIGEST_BITS 224
 # define DIGEST_REFERENCE "RFC 3874"
 # define DIGEST_ALIGN 4
+# define PREFIX_INDEX 3
 #elif HASH_ALGO_SHA512
 # define PROGRAM_NAME "sha512sum"
 # define DIGEST_TYPE_STRING "SHA512"
@@ -76,6 +80,7 @@
 # define DIGEST_BITS 512
 # define DIGEST_REFERENCE "FIPS-180-2"
 # define DIGEST_ALIGN 8
+# define PREFIX_INDEX 4
 #elif HASH_ALGO_SHA384
 # define PROGRAM_NAME "sha384sum"
 # define DIGEST_TYPE_STRING "SHA384"
@@ -83,6 +88,7 @@
 # define DIGEST_BITS 384
 # define DIGEST_REFERENCE "FIPS-180-2"
 # define DIGEST_ALIGN 8
+# define PREFIX_INDEX 5
 #else
 # error "Can't decide which hash algorithm to compile."
 #endif
@@ -135,7 +141,8 @@ enum
 {
   STATUS_OPTION = CHAR_MAX + 1,
   QUIET_OPTION,
-  STRICT_OPTION
+  STRICT_OPTION,
+  TAG_OPTION
 };
 
 static struct option const long_options[] =
@@ -147,11 +154,23 @@ static struct option const long_options[
   { "text", no_argument, NULL, 't' },
   { "warn", no_argument, NULL, 'w' },
   { "strict", no_argument, NULL, STRICT_OPTION },
+  { "tag", no_argument, NULL, TAG_OPTION },
   { GETOPT_HELP_OPTION_DECL },
   { GETOPT_VERSION_OPTION_DECL },
   { NULL, 0, NULL, 0 }
 };
 
+static const char *const prefixes[] =
+{
+  "MD5 ",
+  "SHA1 ",
+  "SHA256 ",
+  "SHA224 ",
+  "SHA512 ",
+  "SHA384 "
+};
+     
+
 void
 usage (int status)
 {
@@ -636,6 +655,42 @@ digest_check (const char *checkfile_name
           && (!strict || n_improperly_formatted_lines == 0));
 }
 
+static void 
+print_filename(char *file)
+{
+  size_t i;
+  /* Translate each NEWLINE byte to the string, "\\n",
+     and each backslash to "\\\\".  */
+  for (i = 0; i < strlen (file); ++i)
+    {
+      switch (file[i])
+        {
+        case '\n':
+          fputs ("\\n", stdout);
+          break;
+
+        case '\\':
+          fputs ("\\\\", stdout);
+          break;
+
+        default:
+          putchar (file[i]);
+          break;
+        }
+    }
+}
+
+static void 
+bsd_print_filename(char *file)
+{
+  size_t i;
+
+  for (i = 0; i < strlen (file); ++i)
+    {
+      putchar(file[i]);
+    }
+}
+
 int
 main (int argc, char **argv)
 {
@@ -646,6 +701,7 @@ main (int argc, char **argv)
   int opt;
   bool ok = true;
   int binary = -1;
+  bool prefix_tag = false;
 
   /* Setting values of global variables.  */
   initialize_main (&argc, &argv);
@@ -660,7 +716,7 @@ main (int argc, char **argv)
      so that processes running in parallel do not intersperse their output.  */
   setvbuf (stdout, NULL, _IOLBF, 0);
 
-  while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
+  while ((opt = getopt_long (argc, argv, "bctwl", long_options, NULL)) != -1)
     switch (opt)
       {
       case 'b':
@@ -690,6 +746,9 @@ main (int argc, char **argv)
       case STRICT_OPTION:
         strict = true;
         break;
+      case TAG_OPTION:
+        prefix_tag = true;
+        break;
       case_GETOPT_HELP_CHAR;
       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
       default:
@@ -754,41 +813,38 @@ main (int argc, char **argv)
             ok = false;
           else
             {
+              if (prefix_tag)
+                {
+                  if(!file_is_binary)
+                    putchar(' ');
+                  printf("%s", prefixes[PREFIX_INDEX]);
+                  putchar('(');
+                  bsd_print_filename(file);
+                  printf(") = ");
+                }
+
               size_t i;
 
               /* Output a leading backslash if the file name contains
                  a newline or backslash.  */
-              if (strchr (file, '\n') || strchr (file, '\\'))
+              if ((strchr (file, '\n') || strchr (file, '\\')) && !prefix_tag)
                 putchar ('\\');
 
               for (i = 0; i < (digest_hex_bytes / 2); ++i)
                 printf ("%02x", bin_buffer[i]);
 
-              putchar (' ');
-              if (file_is_binary)
-                putchar ('*');
-              else
-                putchar (' ');
-
-              /* Translate each NEWLINE byte to the string, "\\n",
-                 and each backslash to "\\\\".  */
-              for (i = 0; i < strlen (file); ++i)
+              if (!prefix_tag)
                 {
-                  switch (file[i])
-                    {
-                    case '\n':
-                      fputs ("\\n", stdout);
-                      break;
-
-                    case '\\':
-                      fputs ("\\\\", stdout);
-                      break;
-
-                    default:
-                      putchar (file[i]);
-                      break;
-                    }
+                  putchar (' ');
+
+                  if (file_is_binary)
+                    putchar ('*');
+                  else
+                    putchar (' ');
+
+                  print_filename(file);
                 }
+
               putchar ('\n');
             }
         }

Reply via email to