pull patches back in from 2.20-2 build
[debian/cpmtools] / cpmls.c
diff --git a/cpmls.c b/cpmls.c
index e2d1786ec4970062401dae95750859eed5f23e56..6bc6bad89b6f757c2651d41d8a3a108c9b89cdd3 100644 (file)
--- a/cpmls.c
+++ b/cpmls.c
@@ -1,11 +1,14 @@
 /* #includes */ /*{{{C}}}*//*{{{*/
+#include "config.h"
+
 #include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "config.h"
-#include "getopt.h"
+#include <time.h>
+
+#include "getopt_.h"
 #include "cpmfs.h"
 /*}}}*/
 
@@ -20,23 +23,42 @@ static int namecmp(const void *a, const void *b)
   return strcmp(*((const char * const *)a),*((const char * const *)b));
 }
 /*}}}*/
+/* onlyuser0 -- do all entries belong to user 0? */ /*{{{*/
+static int onlyuser0(char ** const dirent, int entries)
+{
+  int i;
+
+  for (i=0; i<entries; ++i)
+  {
+    if (dirent[i][0]!='.' && (dirent[i][0]!='0' || dirent[i][1]!='0')) return 0;
+  }
+
+  return 1;
+}
+/*}}}*/
 /* olddir  -- old style output */ /*{{{*/
 static void olddir(char **dirent, int entries)
 {
-  int i,j,k,l,user,announce;
+  int i,j,k,l,user,announce,showuser,files;
 
-  announce=0;
+  showuser=!onlyuser0(dirent,entries);
+  files=0;
   for (user=0; user<32; ++user)
   {
+    announce=1;
     for (i=l=0; i<entries; ++i)
     {
-      if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%33)
+      /* This selects real regular files implicitly, because only those have
+       * the user in their name.  ".", ".." and the password file do not.
+       */
+      if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
       {
-        if (announce==1)
+        ++files;
+        if (announce && showuser)
         {
           printf("User %d\n",user);
+          announce=0;
         }
-        announce=2;
         if (l%4) printf(" : ");
         for (j=2; dirent[i][j] && dirent[i][j]!='.'; ++j) putchar(toupper(dirent[i][j]));
         k=j; while (k<11) { putchar(' '); ++k; }
@@ -45,12 +67,19 @@ static void olddir(char **dirent, int entries)
         for (; k<3; ++k) putchar(' ');
         ++l;
       }
-      if (l && (l%4)==0) putchar('\n');
+      if (l && (l%4)==0)
+      {
+       l = 0;
+       putchar('\n');
+      }        
+    }
+    if (l%4)
+    {
+      putchar('\n');
     }
-    if (l%4) putchar('\n');
-    if (announce==2) announce=1;
   }
-  if (entries==0) printf("No files\n");
+
+  if (files==0) printf("No file\n");
 }
 /*}}}*/
 /* oldddir -- old style long output */ /*{{{*/
@@ -60,7 +89,7 @@ static void oldddir(char **dirent, int entries, struct cpmInode *ino)
   struct cpmStat statbuf;
   struct cpmInode file;
 
-  if (entries)
+  if (entries>2)
   {
     int i,j,k,l,announce,user;
 
@@ -75,7 +104,7 @@ static void oldddir(char **dirent, int entries, struct cpmInode *ino)
       {
         struct tm *tmp;
 
-        if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%33)
+        if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
         {
           if (announce==1)
           {
@@ -93,16 +122,22 @@ static void oldddir(char **dirent, int entries, struct cpmInode *ino)
 
           cpmNamei(ino,dirent[i],&file);
           cpmStat(&file,&statbuf);
-          printf(" %5.1ldK",(statbuf.size+buf.f_bsize-1)/buf.f_bsize*(buf.f_bsize/1024));
+          printf(" %5.1ldK",(long) (statbuf.size+buf.f_bsize-1) /
+                       buf.f_bsize*(buf.f_bsize/1024));
+
           printf(" %6.1ld ",(long)(statbuf.size/128));
           putchar(statbuf.mode&0200 ? ' ' : 'R');
           putchar(statbuf.mode&01000 ? 'S' : ' ');
           putchar(' ');
           if (statbuf.mtime)
           {
-            tmp=gmtime(&statbuf.mtime);
+            tmp=localtime(&statbuf.mtime);
             printf("  %02d-%s-%04d %02d:%02d",tmp->tm_mday,month[tmp->tm_mon],tmp->tm_year+1900,tmp->tm_hour,tmp->tm_min);
-            tmp=gmtime(&statbuf.ctime);
+          }
+          else if (statbuf.ctime) printf("                   ");
+          if (statbuf.ctime)
+          {
+            tmp=localtime(&statbuf.ctime);
             printf("  %02d-%s-%04d %02d:%02d",tmp->tm_mday,month[tmp->tm_mon],tmp->tm_year+1900,tmp->tm_hour,tmp->tm_min);
           }
           putchar('\n');
@@ -124,7 +159,7 @@ static void old3dir(char **dirent, int entries, struct cpmInode *ino)
   struct cpmStat statbuf;
   struct cpmInode file;
 
-  if (entries)
+  if (entries>2)
   {
     int i,j,k,l,announce,user, attrib;
     int totalBytes=0,totalRecs=0;
@@ -138,7 +173,7 @@ static void old3dir(char **dirent, int entries, struct cpmInode *ino)
       {
         struct tm *tmp;
 
-        if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%33)
+        if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
         {
           cpmNamei(ino,dirent[i],&file);
           cpmStat(&file,&statbuf);
@@ -147,7 +182,8 @@ static void old3dir(char **dirent, int entries, struct cpmInode *ino)
           {
             if (user) putchar('\n');
             printf("Directory For Drive A:  User %2.1d\n\n",user);
-            printf("    Name     Bytes   Recs   Attributes   Prot      Update          Create\n");
+            printf("    Name     Bytes   Recs   Attributes   Prot      Update          %s\n",
+               ino->sb->cnotatime ? "Create" : "Access");
             printf("------------ ------ ------ ------------ ------ --------------  --------------\n\n");
           }
           announce=2;
@@ -160,8 +196,9 @@ static void old3dir(char **dirent, int entries, struct cpmInode *ino)
 
           totalBytes+=statbuf.size;
           totalRecs+=(statbuf.size+127)/128;
-          printf(" %5.1ldk",(statbuf.size+buf.f_bsize-1)/buf.f_bsize*(buf.f_bsize/1024));
-          printf(" %6.1ld ",(long)(statbuf.size/128));
+          printf(" %5.1ldk",(long) (statbuf.size+buf.f_bsize-1) /
+                       buf.f_bsize*(buf.f_bsize/1024));
+          printf(" %6.1ld ",(long)((statbuf.size+127)/128));
           putchar((attrib & CPM_ATTR_F1)   ? '1' : ' ');
           putchar((attrib & CPM_ATTR_F2)   ? '2' : ' ');
           putchar((attrib & CPM_ATTR_F3)   ? '3' : ' ');          
@@ -174,10 +211,22 @@ static void old3dir(char **dirent, int entries, struct cpmInode *ino)
           else if (attrib & CPM_ATTR_PWWRITE) printf("Write  ");
           else if (attrib & CPM_ATTR_PWDEL)   printf("Delete "); 
           else printf("None   ");
-          tmp=gmtime(&statbuf.mtime);
-          printf("%02d/%02d/%02d %02d:%02d  ",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
-          tmp=gmtime(&statbuf.ctime);
-          printf("%02d/%02d/%02d %02d:%02d",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
+          if (statbuf.mtime)
+          {
+            tmp=localtime(&statbuf.mtime);
+            printf("%02d/%02d/%02d %02d:%02d  ",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
+          }
+          else printf("                ");
+          if (ino->sb->cnotatime && statbuf.ctime)
+          {
+            tmp=localtime(&statbuf.ctime);
+            printf("%02d/%02d/%02d %02d:%02d",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
+          }
+          else if (!ino->sb->cnotatime && statbuf.atime)
+          {
+            tmp=localtime(&statbuf.atime);
+            printf("%02d/%02d/%02d %02d:%02d",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
+          }
           putchar('\n');
           ++l;
         }
@@ -210,7 +259,7 @@ static void ls(char **dirent, int entries, struct cpmInode *ino, int l, int c, i
     announce=0;
     for (i=0; i<entries; ++i) if (dirent[i][0]!='.')
     {
-      if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%33)
+      if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
       {
         if (announce==0)
         {
@@ -224,7 +273,7 @@ static void ls(char **dirent, int entries, struct cpmInode *ino, int l, int c, i
           cpmNamei(ino,dirent[i],&file);
           cpmStat(&file,&statbuf);
         }
-        if (iflag) printf("%4ld ",statbuf.ino);
+        if (iflag) printf("%4ld ",(long) statbuf.ino);
         if (l)
         {
           struct tm *tmp;
@@ -245,7 +294,7 @@ static void ls(char **dirent, int entries, struct cpmInode *ino, int l, int c, i
           printf(" %-2d ",dir[i].user);
 #endif
           printf("%8.1ld ",(long)statbuf.size);
-          tmp=gmtime(c ? &statbuf.ctime : &statbuf.mtime);
+          tmp=localtime(c ? &statbuf.ctime : &statbuf.mtime);
           printf("%s %02d ",month[tmp->tm_mon],tmp->tm_mday);
           if ((c ? statbuf.ctime : statbuf.mtime)<(now-182*24*3600)) printf("%04d  ",tmp->tm_year+1900);
           else printf("%02d:%02d ",tmp->tm_hour,tmp->tm_min);
@@ -272,7 +321,7 @@ static void lsattr(char **dirent, int entries, struct cpmInode *ino)
     announce=0;
     for (i=0; i<entries; ++i) if (dirent[i][0]!='.')
     {
-      if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%33)
+      if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
       {
         if (announce==0)
         {
@@ -310,22 +359,24 @@ int main(int argc, char *argv[])
   /* variables */ /*{{{*/
   const char *err;
   const char *image;
-  const char *format=FORMAT;
+  const char *format;
   const char *devopts=NULL;
   int c,usage=0;
-  struct cpmSuperBlock drive;
+  struct cpmSuperBlock super;
   struct cpmInode root;
   int style=0;
   int changetime=0;
+  int uppercase=0;
   int inode=0;
   char **gargv;
   int gargc;
   static char starlit[2]="*";
-  static char * const star[]={starlit};
+  static char * const star[]={ starlit };
   /*}}}*/
 
   /* parse options */ /*{{{*/
-  while ((c=getopt(argc,argv,"cT:f:ih?dDFlA"))!=EOF) switch(c)
+  if (!(format=getenv("CPMTOOLSFMT"))) format=FORMAT;
+  while ((c=getopt(argc,argv,"cT:f:ih?dDFlAu"))!=EOF) switch(c)
   {
     case 'f': format=optarg; break;
     case 'T': devopts=optarg; break;
@@ -338,6 +389,7 @@ int main(int argc, char *argv[])
     case 'A': style=5; break;
     case 'c': changetime=1; break;
     case 'i': inode=1; break;
+    case 'u': uppercase=1; break;
   }
 
   if (optind==argc) usage=1;
@@ -345,17 +397,25 @@ int main(int argc, char *argv[])
 
   if (usage)
   {
-    fprintf(stderr,"Usage: %s [-f format] [-T libdsk-type] [-d|-D|-F|-A|[-l][-c][-i]] image [file ...]\n",cmd);
+#ifdef HAVE_LIBDSK_H
+    fprintf(stderr,"Usage: %s [-f format] [-T libdsk-type] [-d|-D|-F|-A|[-l][-c][-i]] [-u] image [file ...]\n",cmd);
+#else
+    fprintf(stderr,"Usage: %s [-f format] [-d|-D|-F|-A|[-l][-c][-i]] [-u] image [file ...]\n",cmd);
+#endif
     exit(1);
   }
   /*}}}*/
   /* open image */ /*{{{*/
-  if ((err=Device_open(&drive.dev,image,O_RDONLY,devopts))) 
+  if ((err=Device_open(&super.dev,image,O_RDONLY,devopts))) 
+  {
+    fprintf(stderr,"%s: cannot open %s (%s)\n",cmd,image,err);
+    exit(1);
+  }
+  if (cpmReadSuper(&super,&root,format,uppercase)==-1)
   {
-    fprintf(stderr,"%s: can not open %s (%s)\n",cmd,image,err);
+    fprintf(stderr,"%s: cannot read superblock (%s)\n",cmd,boo);
     exit(1);
   }
-  cpmReadSuper(&drive,&root,format);
   /*}}}*/
   if (optind<argc) cpmglob(optind,argc,argv,&root,&gargc,&gargv);
   else cpmglob(0,1,star,&root,&gargc,&gargv);
@@ -364,5 +424,7 @@ int main(int argc, char *argv[])
   else if (style==3) old3dir(gargv,gargc,&root);
   else if (style==5) lsattr(gargv, gargc, &root); 
   else ls(gargv,gargc,&root,style==4,changetime,inode);
+  cpmglobfree(gargv,gargc);
+  cpmUmount(&super);
   exit(0);
 }