From: mitch@clsi.UUCP (Mitchell Perilstein)
Subject: suggestion for ls
Organization: GNUs Not Usenet
Distribution: gnu
Date: Sun, 3 Jan 1993 22:11:58 GMT

The following patches to fileutils-3.4 adds Yet Another Switch to ls:

     -M, --mountpoints
          Indicate directories which are mountpoints by appending
          a  `^'  character to their filename. If the long format
          is also specified, indicates which device is mounted on
          the mountpoint and the host, if remote.

Here is some sample output:

$ ls -M /
backup          export          pcfs            var^
bin             home^           sbin            vmunix
boot            kadb            sys             vmunix.GENERIC
clsi^           lib             tmp             vmunix.old
dev             lost+found      tmp_rex
etc             mnt             usr^

$ ls -lM /
total 4820
drwxrwxrwx   3 root     users         512 Jan  2 14:32 backup
lrwxrwxrwx   1 root     wheel           7 May  1  1992 bin -> usr/bin
-r--r--r--   1 root     bin        140904 May  1  1992 boot
drwxr-xr-x   8 root     wheel         512 Jan  1 22:58 clsi <- /dev/sd0e
drwxr-sr-x   2 bin      staff       11264 Dec 21 14:16 dev
drwxr-sr-x   9 bin      staff        3072 Jan  3 12:20 etc
drwxr-sr-x   4 root     wheel         512 May  1  1992 export
drwxr-xr-x  11 root     wheel         512 Jan  1 23:04 home <- /dev/sd0h
-rwxr-xr-x   1 root     wheel      311163 May  1  1992 kadb
lrwxrwxrwx   1 root     wheel           7 May  1  1992 lib -> usr/lib
..

$ ls -lM /home/dev
total 6
drwxrws---  13 markb    rvcg          512 Dec 11 12:50 codegen <- dubhe:/dubhe/codegen
drwxrws---   8 hank     users         512 Nov 11 14:22 internal <- unuk:/unuk/internal
drwxrwsr-x   7 daniel   third         512 Jan  3 16:55 openhdl <- pollux:/pollux/openhdl
drwxrws---  22 glenn    synth         512 Dec 18 15:49 synthesis <- capella:/capella/synthesis
..

--> NOTE
--> Tested only on Sun4 SunOS 4.1 and RISC Ultrix V4.2A. There are
--> some platform-dependent things in mountlist.c which I could not
--> test; they might even produce syntax errors.

Recursive context diffs follow.  Thanks for such a nice and easily
maintainable product!

Respectfully,
---
 Mitchell N. Perilstein   CAD Language Systems, Inc.   410-992-5700 x225 
 Member, League for Programming Freedom.  Mail lpf@uunet.uu.net for info.


diff -cr fileutils-3.4.orig/ChangeLog fileutils-3.4/ChangeLog
*** fileutils-3.4.orig/ChangeLog	Thu Oct 29 15:23:14 1992
--- fileutils-3.4/ChangeLog	Fri Jan  1 17:41:26 1993
***************
*** 1,3 ****
--- 1,10 ----
+ Fri Jan  1 17:31:54 1993  Mitchell Perilstein  (mitch@clsi.com)
+ 
+ 	* mountlist.{c,h}: read_filesystem_list records inode of mountdir.
+ 
+ 	* Makefile.in, ls.1, ls.c: Add -M,--mountpoint option. ls calls
+ 	read_filesystem_list; uses dev and inode to compare mountponts.
+ 
  Thu Oct 29 14:57:21 1992  David J. MacKenzie  (djm@kropotkin.gnu.ai.mit.edu)
  
  	* Version 3.4.
Common subdirectories: fileutils-3.4.orig/lib and fileutils-3.4/lib
Common subdirectories: fileutils-3.4.orig/man and fileutils-3.4/man
Common subdirectories: fileutils-3.4.orig/src and fileutils-3.4/src
diff -cr fileutils-3.4.orig/lib/mountlist.c fileutils-3.4/lib/mountlist.c
*** fileutils-3.4.orig/lib/mountlist.c	Sat Apr 18 15:33:08 1992
--- fileutils-3.4/lib/mountlist.c	Fri Jan  1 17:39:27 1993
***************
*** 17,22 ****
--- 17,23 ----
  
  #include <stdio.h>
  #include <sys/types.h>
+ #include <sys/stat.h>
  #include "mountlist.h"
  
  #ifdef STDC_HEADERS
***************
*** 169,174 ****
--- 170,176 ----
    struct mount_entry *mount_list;
    struct mount_entry *me;
    struct mount_entry *mtail;
+   struct stat statbuf;  
  
    /* Start the list off with a dummy entry. */
    me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
***************
*** 195,200 ****
--- 197,206 ----
  	me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry));
  	me->me_devname = xstrdup (mnt->mnt_fsname);
  	me->me_mountdir = xstrdup (mnt->mnt_dir);
+ 	if (stat (mnt->mnt_dir, &statbuf) >= 0)
+ 	    me->me_ino = statbuf.st_ino;
+ 	else
+ 	    me->me_ino = 0;
  	me->me_type = xstrdup (mnt->mnt_type);
  	devopt = strstr (mnt->mnt_opts, "dev=");
  	if (devopt)
***************
*** 233,238 ****
--- 239,248 ----
  	me->me_mountdir = xstrdup (fsp->f_mntonname);
  	me->me_type = fstype_to_string (fsp->f_type);
  	me->me_dev = -1;	/* Magic; means not known yet. */
+ 	if (stat (mnt->mnt_dir, &statbuf) >= 0)
+ 	    me->me_ino = statbuf.st_ino;
+ 	else
+ 	    me->me_ino = 0;
  	me->me_next = NULL;
  
  	/* Add to the linked list. */
***************
*** 257,262 ****
--- 267,276 ----
  	me->me_mountdir = xstrdup (fsd.fd_req.path);
  	me->me_type = gt_names[fsd.fd_req.fstype];
  	me->me_dev = fsd.fd_req.dev;
+ 	if (stat (fsd.fd_req.path, &statbuf) >= 0)
+ 	    me->me_ino = statbuf.st_ino;
+ 	else
+ 	    me->me_ino = 0;
  	me->me_next = NULL;
  
  	/* Add to the linked list. */
***************
*** 290,295 ****
--- 304,313 ----
  #endif
  	me->me_mountdir = xstrdup (mnt.mt_filsys);
  	me->me_dev = -1;	/* Magic; means not known yet. */
+ 	if (stat (mnt.mt_filsys, &statbuf) >= 0)
+ 	    me->me_ino = statbuf.st_ino;
+ 	else
+ 	    me->me_ino = 0;
  	me->me_type = "";
  #ifdef GETFSTYP			/* SVR3.  */
  	if (need_fs_type)
***************
*** 332,337 ****
--- 350,359 ----
  	me->me_mountdir = xstrdup (mnt.mnt_mountp);
  	me->me_type = xstrdup (mnt.mnt_fstype);
  	me->me_dev = -1;	/* Magic; means not known yet. */
+ 	if (stat (mnt.mnt_mountp, &statbuf) >= 0)
+ 	    me->me_ino = statbuf.st_ino;
+ 	else
+ 	    me->me_ino = 0;
  	me->me_next = NULL;
  
  	/* Add to the linked list. */
***************
*** 384,389 ****
--- 406,415 ----
  	me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
  	me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
  	me->me_dev = -1;	/* vmt_fsid might be the info we want.  */
+ 	if (stat (me->me_mountdir, &statbuf) >= 0)
+ 	    me->me_ino = statbuf.st_ino;
+ 	else
+ 	    me->me_ino = 0;
  	me->me_next = NULL;
  
  	/* Add to the linked list. */
diff -cr fileutils-3.4.orig/lib/mountlist.h fileutils-3.4/lib/mountlist.h
*** fileutils-3.4.orig/lib/mountlist.h	Wed Mar 25 12:33:05 1992
--- fileutils-3.4/lib/mountlist.h	Thu Dec 31 15:27:47 1992
***************
*** 22,27 ****
--- 22,28 ----
    char *me_mountdir;		/* Mount point directory pathname. */
    char *me_type;		/* "nfs", "4.2", etc. */
    dev_t me_dev;			/* Device number of me_mountdir. */
+   ino_t me_ino;			/* Inode of me_mountdir. */
    struct mount_entry *me_next;
  };
  
diff -cr fileutils-3.4.orig/man/ls.1 fileutils-3.4/man/ls.1
*** fileutils-3.4.orig/man/ls.1	Wed Oct 14 23:17:11 1992
--- fileutils-3.4/man/ls.1	Fri Jan  1 17:44:03 1993
***************
*** 3,14 ****
  ls, dir, vdir \- list contents of directories
  .SH SYNOPSIS
  .B ls
! [\-abcdgiklmnpqrstuxABCFLNQRSUX1] [\-w cols] [\-T cols] [\-I pattern]
  [\-\-all] [\-\-escape] [\-\-directory] [\-\-inode] [\-\-kilobytes]
  [\-\-numeric-uid-gid] [\-\-hide-control-chars] [\-\-reverse] [\-\-size]
  [\-\-width=cols] [\-\-tabsize=cols] [\-\-almost-all] [\-\-ignore-backups]
  [\-\-classify] [\-\-file-type] [\-\-ignore=pattern] [\-\-dereference]
! [\-\-literal] [\-\-quote-name] [\-\-recursive]
  [\-\-sort={none,time,size,extension}]
  [\-\-format={long,verbose,commas,across,vertical,single-column}]
  [\-\-time={atime,access,use,ctime,status}] [path...]
--- 3,14 ----
  ls, dir, vdir \- list contents of directories
  .SH SYNOPSIS
  .B ls
! [\-abcdgiklmnpqrstuxABCFLMNQRSUX1] [\-w cols] [\-T cols] [\-I pattern]
  [\-\-all] [\-\-escape] [\-\-directory] [\-\-inode] [\-\-kilobytes]
  [\-\-numeric-uid-gid] [\-\-hide-control-chars] [\-\-reverse] [\-\-size]
  [\-\-width=cols] [\-\-tabsize=cols] [\-\-almost-all] [\-\-ignore-backups]
  [\-\-classify] [\-\-file-type] [\-\-ignore=pattern] [\-\-dereference]
! [\-\-literal] [\-\-mountpoints] [\-\-quote-name] [\-\-recursive]
  [\-\-sort={none,time,size,extension}]
  [\-\-format={long,verbose,commas,across,vertical,single-column}]
  [\-\-time={atime,access,use,ctime,status}] [path...]
***************
*** 119,124 ****
--- 119,129 ----
  .I "\-L, \-\-dereference"
  List the files linked to by symbolic links instead of listing the
  contents of the links.
+ .TP
+ .I "\-M, \-\-mountpoints"
+ Indicate directories which are mountpoints by appending a `^' character
+ to their filename. If the long format is also specified, indicates which
+ device is mounted on the mountpoint and the host, if remote.
  .TP
  .I "\-N, \-\-literal"
  Do not quote file names.
diff -cr fileutils-3.4.orig/src/ls.c fileutils-3.4/src/ls.c
*** fileutils-3.4.orig/src/ls.c	Wed Oct 14 23:08:47 1992
--- fileutils-3.4/src/ls.c	Fri Jan  1 18:18:52 1993
***************
*** 45,50 ****
--- 45,51 ----
  #include <getopt.h>
  #include <fnmatch.h>
  #include "system.h"
+ #include "mountlist.h"
  
  #ifndef S_IEXEC
  #define S_IEXEC S_IXUSR
***************
*** 180,185 ****
--- 181,191 ----
  
  /* The name the program was run with, stripped of any leading path. */
  char *program_name;
+ 
+ /* List of mountpoints. Used only when show_mountpoints (-M) is nonzero. */
+ 
+ struct mount_entry *mountpoint_list;
+ 
  
  /* Option flags */
  
***************
*** 263,268 ****
--- 269,280 ----
  
  enum indicator_style indicator_style;
  
+ /* Nonzero means show when a directory is a mountpoint; `^' is an 
+    displayed unless -l; `filename <- host:dir' when -l. Controlled 
+    by -M. */
+ 
+ int show_mountpoints;
+ 
  /* Nonzero means mention the inode number of each file.  -i  */
  
  int print_inode;
***************
*** 367,373 ****
    format_needs_stat = sort_type == sort_time || sort_type == sort_size
      || format == long_format
      || trace_links || trace_dirs || indicator_style != none
!     || print_block_size || print_inode;
  
    nfiles = 100;
    files = (struct file *) xmalloc (sizeof (struct file) * nfiles);
--- 379,386 ----
    format_needs_stat = sort_type == sort_time || sort_type == sort_size
      || format == long_format
      || trace_links || trace_dirs || indicator_style != none
!     || print_block_size || print_inode 
!     || show_mountpoints;
  
    nfiles = 100;
    files = (struct file *) xmalloc (sizeof (struct file) * nfiles);
***************
*** 437,442 ****
--- 450,456 ----
    {"file-type", 0, 0, 'F'},
    {"ignore", 1, 0, 'I'},
    {"dereference", 0, 0, 'L'},
+   {"mountpoints", 0, 0, 'M'},
    {"literal", 0, 0, 'N'},
    {"quote-name", 0, 0, 'Q'},
    {"recursive", 0, 0, 'R'},
***************
*** 535,540 ****
--- 549,555 ----
    really_all_files = 0;
    ignore_patterns = 0;
    quote_as_string = 0;
+   show_mountpoints = 0;
  
    p = getenv ("COLUMNS");
    line_length = p ? atoi (p) : 80;
***************
*** 551,557 ****
    p = getenv ("TABSIZE");
    tabsize = p ? atoi (p) : 8;
  
!   while ((c = getopt_long (argc, argv, "abcdgiklmnpqrstuw:xABCFI:LNQRST:UX1",
  			   long_options, (int *) 0)) != EOF)
      {
        switch (c)
--- 566,572 ----
    p = getenv ("TABSIZE");
    tabsize = p ? atoi (p) : 8;
  
!   while ((c = getopt_long (argc, argv, "abcdgiklmnpqrstuw:xABCFI:LMNQRST:UX1",
  			   long_options, (int *) 0)) != EOF)
      {
        switch (c)
***************
*** 663,668 ****
--- 678,688 ----
  	  qmark_funny_chars = 0;
  	  break;
  	  
+ 	case 'M':
+ 	  show_mountpoints = 1;
+ 	  mountpoint_list = 0;
+ 	  break;
+ 	  
  	case 'Q':
  	  quote_as_string = 1;
  	  quote_funny_chars = 1;
***************
*** 1141,1146 ****
--- 1161,1218 ----
  
    return 1;
  }
+ 
+ /* Based on cwd and pending list, calculate whole path to a file. 
+    Returns allocated string. */
+ char *
+ get_whole_path(file)
+      char *file;
+ {
+   char *xgetcwd();
+   char *result;
+   
+   if (dir_defaulted)
+     {
+       char *cwd = xgetcwd();	/* should error check this call?? */
+       int cwdlen = strlen(cwd);
+       
+       result = (char *)xrealloc (cwd, cwdlen + strlen(file) + 2);
+       result[cwdlen] = '\\';
+       strcat(&result[cwdlen + 1], file) ;
+     } 
+   else 
+     { 
+       ;
+       
+     }	
+   return result;
+ }
+ 
+ /* Returns char pointer to name of device if DIR is a mountpoint, otherwise
+    returns NULL. */
+ char *
+ is_mountpoint(dir)
+     struct file *dir;
+ {
+     struct mount_entry *me;
+ 
+     /* Init the mount list. Only do this first time it's needed. */
+     if (!mountpoint_list)
+       {
+          mountpoint_list = read_filesystem_list(1, 1);
+ 	 if (!mountpoint_list)
+ 	   return (char *)NULL; /* Nonfatal error, just keep going. */
+ 	  			/* At worst, the listing will be wrong. */
+       }    
+ 
+     /* Compare directory against every mountpoint. Compare device 
+        numbers and then inode numbers. */
+     for (me = mountpoint_list; NULL != me; me = me->me_next)
+ 	if (me->me_dev == dir->stat.st_dev && me->me_ino == dir->stat.st_ino) 
+ 	    return me->me_devname;
+ 
+     return (char *)NULL;
+ }
  
  /* Sort the files now in the table.  */
  
***************
*** 1416,1422 ****
  	    print_type_indicator (f->linkmode);
  	}
      }
!   else if (indicator_style != none)
      print_type_indicator (f->stat.st_mode);
  }
  
--- 1488,1504 ----
  	    print_type_indicator (f->linkmode);
  	}
      }
!   else if ((f->filetype == directory || f->filetype == arg_directory)
! 	   && show_mountpoints)
!     {
!       char *devname = is_mountpoint (f);
! 	
!       if (NULL != devname)
! 	printf (" <- %s", devname);
!       else if (indicator_style != none)
! 	print_type_indicator (f->stat.st_mode);
!     }
!  else if (indicator_style != none)
      print_type_indicator (f->stat.st_mode);
  }
  
***************
*** 1506,1513 ****
  
    print_name_with_quoting (f->name);
  
!   if (indicator_style != none)
!     print_type_indicator (f->stat.st_mode);
  }
  
  void
--- 1588,1604 ----
  
    print_name_with_quoting (f->name);
  
!   if ((f->filetype == directory || f->filetype == arg_directory)
!       && show_mountpoints)
!     {
!       if (NULL != is_mountpoint (f))	
! 	putchar ('^');
!       else if (indicator_style != none)
! 	  print_type_indicator (f->stat.st_mode);
!     }
!   else
!     if (indicator_style != none)
!       print_type_indicator (f->stat.st_mode);
  }
  
  void
***************
*** 1799,1805 ****
  usage ()
  {
    fprintf (stderr, "\
! Usage: %s [-abcdgiklmnpqrstuxABCFLNQRSUX1] [-w cols] [-T cols] [-I pattern]\n\
         [--all] [--escape] [--directory] [--inode] [--kilobytes] [--literal]\n\
         [--numeric-uid-gid] [--hide-control-chars] [--reverse] [--size]\n\
         [--width=cols] [--tabsize=cols] [--almost-all] [--ignore-backups]\n",
--- 1890,1896 ----
  usage ()
  {
    fprintf (stderr, "\
! Usage: %s [-abcdgiklmnpqrstuxABCFLMNQRSUX1] [-w cols] [-T cols] [-I pattern]\n\
         [--all] [--escape] [--directory] [--inode] [--kilobytes] [--literal]\n\
         [--numeric-uid-gid] [--hide-control-chars] [--reverse] [--size]\n\
         [--width=cols] [--tabsize=cols] [--almost-all] [--ignore-backups]\n",
***************
*** 1806,1812 ****
  	   program_name);
    fprintf (stderr, "\
         [--classify] [--file-type] [--ignore=pattern] [--dereference]\n\
!        [--quote-name] [--recursive] [--sort={none,time,size,extension}]\n\
         [--format={long,verbose,commas,across,vertical,single-column}]\n\
         [--time={atime,access,use,ctime,status}] [path...]\n");
    exit (1);
--- 1897,1904 ----
  	   program_name);
    fprintf (stderr, "\
         [--classify] [--file-type] [--ignore=pattern] [--dereference]\n\
!        [--mountpoints] [--quote-name] [--recursive]\n\
!        [--sort={none,time,size,extension}]\n\
         [--format={long,verbose,commas,across,vertical,single-column}]\n\
         [--time={atime,access,use,ctime,status}] [path...]\n");
    exit (1);


Newsgroups: gnu.utils.bug