1 /* #includes */ /*{{{C}}}*//*{{{*/
18 /* variables */ /*{{{*/
19 static const char * const month[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
22 /* namecmp -- compare two entries */ /*{{{*/
23 static int namecmp(const void *a, const void *b)
25 if (**((const char * const *)a)=='[') return -1;
26 return strcmp(*((const char * const *)a),*((const char * const *)b));
29 /* olddir -- old style output */ /*{{{*/
30 static void olddir(char **dirent, int entries)
32 int i,j,k,l,user,announce;
35 for (user=0; user<32; ++user)
37 for (i=l=0; i<entries; ++i)
39 if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
43 printf("User %d\n",user);
46 if (l%4) printf(" : ");
47 for (j=2; dirent[i][j] && dirent[i][j]!='.'; ++j) putchar(toupper(dirent[i][j]));
48 k=j; while (k<11) { putchar(' '); ++k; }
49 if (dirent[i][j]=='.') ++j;
50 for (k=0; dirent[i][j]; ++j,++k) putchar(toupper(dirent[i][j]));
51 for (; k<3; ++k) putchar(' ');
63 if (announce==2) announce=1;
65 if (entries==0) printf("No files\n");
68 /* oldddir -- old style long output */ /*{{{*/
69 static void oldddir(char **dirent, int entries, struct cpmInode *ino)
72 struct cpmStat statbuf;
77 int i,j,k,l,announce,user;
79 qsort(dirent,entries,sizeof(char*),namecmp);
81 printf(" Name Bytes Recs Attr update create\n");
82 printf("------------ ------ ------ ---- ----------------- -----------------\n");
84 for (l=user=0; user<32; ++user)
86 for (i=0; i<entries; ++i)
90 if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
94 printf("\nUser %d:\n\n",user);
95 printf(" Name Bytes Recs Attr update create\n");
96 printf("------------ ------ ------ ---- ----------------- -----------------\n");
99 for (j=2; dirent[i][j] && dirent[i][j]!='.'; ++j) putchar(toupper(dirent[i][j]));
100 k=j; while (k<10) { putchar(' '); ++k; }
102 if (dirent[i][j]=='.') ++j;
103 for (k=0; dirent[i][j]; ++j,++k) putchar(toupper(dirent[i][j]));
104 for (; k<3; ++k) putchar(' ');
106 cpmNamei(ino,dirent[i],&file);
107 cpmStat(&file,&statbuf);
108 printf(" %5.1ldK",(long) (statbuf.size+buf.f_bsize-1) /
109 buf.f_bsize*(buf.f_bsize/1024));
111 printf(" %6.1ld ",(long)(statbuf.size/128));
112 putchar(statbuf.mode&0200 ? ' ' : 'R');
113 putchar(statbuf.mode&01000 ? 'S' : ' ');
117 tmp=localtime(&statbuf.mtime);
118 printf(" %02d-%s-%04d %02d:%02d",tmp->tm_mday,month[tmp->tm_mon],tmp->tm_year+1900,tmp->tm_hour,tmp->tm_min);
119 tmp=localtime(&statbuf.ctime);
120 printf(" %02d-%s-%04d %02d:%02d",tmp->tm_mday,month[tmp->tm_mon],tmp->tm_year+1900,tmp->tm_hour,tmp->tm_min);
126 if (announce==2) announce=1;
128 printf("%5.1d Files occupying %6.1ldK",l,(buf.f_bused*buf.f_bsize)/1024);
129 printf(", %7.1ldK Free.\n",(buf.f_bfree*buf.f_bsize)/1024);
131 else printf("No files found\n");
134 /* old3dir -- old CP/M Plus style long output */ /*{{{*/
135 static void old3dir(char **dirent, int entries, struct cpmInode *ino)
137 struct cpmStatFS buf;
138 struct cpmStat statbuf;
139 struct cpmInode file;
143 int i,j,k,l,announce,user, attrib;
144 int totalBytes=0,totalRecs=0;
146 qsort(dirent,entries,sizeof(char*),namecmp);
149 for (l=0,user=0; user<32; ++user)
151 for (i=0; i<entries; ++i)
155 if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
157 cpmNamei(ino,dirent[i],&file);
158 cpmStat(&file,&statbuf);
159 cpmAttrGet(&file, &attrib);
162 if (user) putchar('\n');
163 printf("Directory For Drive A: User %2.1d\n\n",user);
164 printf(" Name Bytes Recs Attributes Prot Update Create\n");
165 printf("------------ ------ ------ ------------ ------ -------------- --------------\n\n");
168 for (j=2; dirent[i][j] && dirent[i][j]!='.'; ++j) putchar(toupper(dirent[i][j]));
169 k=j; while (k<10) { putchar(' '); ++k; }
171 if (dirent[i][j]=='.') ++j;
172 for (k=0; dirent[i][j]; ++j,++k) putchar(toupper(dirent[i][j]));
173 for (; k<3; ++k) putchar(' ');
175 totalBytes+=statbuf.size;
176 totalRecs+=(statbuf.size+127)/128;
177 printf(" %5.1ldk",(long) (statbuf.size+buf.f_bsize-1) /
178 buf.f_bsize*(buf.f_bsize/1024));
179 printf(" %6.1ld ",(long)(statbuf.size/128));
180 putchar((attrib & CPM_ATTR_F1) ? '1' : ' ');
181 putchar((attrib & CPM_ATTR_F2) ? '2' : ' ');
182 putchar((attrib & CPM_ATTR_F3) ? '3' : ' ');
183 putchar((attrib & CPM_ATTR_F4) ? '4' : ' ');
184 putchar((statbuf.mode&(S_IWUSR|S_IWGRP|S_IWOTH)) ? ' ' : 'R');
185 putchar((attrib & CPM_ATTR_SYS) ? 'S' : ' ');
186 putchar((attrib & CPM_ATTR_ARCV) ? 'A' : ' ');
188 if (attrib & CPM_ATTR_PWREAD) printf("Read ");
189 else if (attrib & CPM_ATTR_PWWRITE) printf("Write ");
190 else if (attrib & CPM_ATTR_PWDEL) printf("Delete ");
191 else printf("None ");
192 tmp=localtime(&statbuf.mtime);
193 printf("%02d/%02d/%02d %02d:%02d ",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
194 tmp=localtime(&statbuf.ctime);
195 printf("%02d/%02d/%02d %02d:%02d",tmp->tm_mon+1,tmp->tm_mday,tmp->tm_year%100,tmp->tm_hour,tmp->tm_min);
200 if (announce==2) announce=1;
202 printf("\nTotal Bytes = %6.1dk ",(totalBytes+1023)/1024);
203 printf("Total Records = %7.1d ",totalRecs);
204 printf("Files Found = %4.1d\n",l);
205 printf("Total 1k Blocks = %6.1ld ",(buf.f_bused*buf.f_bsize)/1024);
206 printf("Used/Max Dir Entries For Drive A: %4.1ld/%4.1ld\n",buf.f_files-buf.f_ffree,buf.f_files);
208 else printf("No files found\n");
211 /* ls -- UNIX style output */ /*{{{*/
212 static void ls(char **dirent, int entries, struct cpmInode *ino, int l, int c, int iflag)
214 int i,user,announce,any;
216 struct cpmStat statbuf;
217 struct cpmInode file;
220 qsort(dirent,entries,sizeof(char*),namecmp);
223 for (user=0; user<32; ++user)
226 for (i=0; i<entries; ++i) if (dirent[i][0]!='.')
228 if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
232 if (any) putchar('\n');
233 printf("%d:\n",user);
239 cpmNamei(ino,dirent[i],&file);
240 cpmStat(&file,&statbuf);
242 if (iflag) printf("%4ld ",(long) statbuf.ino);
247 putchar(S_ISDIR(statbuf.mode) ? 'd' : '-');
248 putchar(statbuf.mode&0400 ? 'r' : '-');
249 putchar(statbuf.mode&0200 ? 'w' : '-');
250 putchar(statbuf.mode&0100 ? 'x' : '-');
251 putchar(statbuf.mode&0040 ? 'r' : '-');
252 putchar(statbuf.mode&0020 ? 'w' : '-');
253 putchar(statbuf.mode&0010 ? 'x' : '-');
254 putchar(statbuf.mode&0004 ? 'r' : '-');
255 putchar(statbuf.mode&0002 ? 'w' : '-');
256 putchar(statbuf.mode&0001 ? 'x' : '-');
258 putchar(statbuf.flags&FLAG_PUBLIC ? 'p' : '-');
259 putchar(dir[i].flags&FLAG_SYSTEM ? 's' : '-');
260 printf(" %-2d ",dir[i].user);
262 printf("%8.1ld ",(long)statbuf.size);
263 tmp=localtime(c ? &statbuf.ctime : &statbuf.mtime);
264 printf("%s %02d ",month[tmp->tm_mon],tmp->tm_mday);
265 if ((c ? statbuf.ctime : statbuf.mtime)<(now-182*24*3600)) printf("%04d ",tmp->tm_year+1900);
266 else printf("%02d:%02d ",tmp->tm_hour,tmp->tm_min);
268 printf("%s\n",dirent[i]+2);
274 /* lsattr -- output something like e2fs lsattr */ /*{{{*/
275 static void lsattr(char **dirent, int entries, struct cpmInode *ino)
277 int i,user,announce,any;
278 struct cpmStat statbuf;
279 struct cpmInode file;
282 qsort(dirent,entries,sizeof(char*),namecmp);
285 for (user=0; user<32; ++user)
288 for (i=0; i<entries; ++i) if (dirent[i][0]!='.')
290 if (dirent[i][0]=='0'+user/10 && dirent[i][1]=='0'+user%10)
294 if (any) putchar('\n');
295 printf("%d:\n",user);
300 cpmNamei(ino,dirent[i],&file);
301 cpmStat(&file,&statbuf);
302 cpmAttrGet(&file, &attrib);
304 putchar ((attrib & CPM_ATTR_F1) ? '1' : '-');
305 putchar ((attrib & CPM_ATTR_F2) ? '2' : '-');
306 putchar ((attrib & CPM_ATTR_F3) ? '3' : '-');
307 putchar ((attrib & CPM_ATTR_F4) ? '4' : '-');
308 putchar ((attrib & CPM_ATTR_SYS) ? 's' : '-');
309 putchar ((attrib & CPM_ATTR_ARCV) ? 'a' : '-');
310 putchar ((attrib & CPM_ATTR_PWREAD) ? 'r' : '-');
311 putchar ((attrib & CPM_ATTR_PWWRITE) ? 'w' : '-');
312 putchar ((attrib & CPM_ATTR_PWDEL) ? 'e' : '-');
314 printf(" %s\n",dirent[i]+2);
321 const char cmd[]="cpmls";
323 int main(int argc, char *argv[])
325 /* variables */ /*{{{*/
328 const char *format=FORMAT;
329 const char *devopts=NULL;
331 struct cpmSuperBlock drive;
332 struct cpmInode root;
338 static char starlit[2]="*";
339 static char * const star[]={starlit};
342 /* parse options */ /*{{{*/
343 while ((c=getopt(argc,argv,"cT:f:ih?dDFlA"))!=EOF) switch(c)
345 case 'f': format=optarg; break;
346 case 'T': devopts=optarg; break;
348 case '?': usage=1; break;
349 case 'd': style=1; break;
350 case 'D': style=2; break;
351 case 'F': style=3; break;
352 case 'l': style=4; break;
353 case 'A': style=5; break;
354 case 'c': changetime=1; break;
355 case 'i': inode=1; break;
358 if (optind==argc) usage=1;
359 else image=argv[optind++];
364 fprintf(stderr,"Usage: %s [-f format] [-T libdsk-type] [-d|-D|-F|-A|[-l][-c][-i]] image [file ...]\n",cmd);
366 fprintf(stderr,"Usage: %s [-f format] [-d|-D|-F|-A|[-l][-c][-i]] image [file ...]\n",cmd);
371 /* open image */ /*{{{*/
372 if ((err=Device_open(&drive.dev,image,O_RDONLY,devopts)))
374 fprintf(stderr,"%s: can not open %s (%s)\n",cmd,image,err);
377 cpmReadSuper(&drive,&root,format);
379 if (optind<argc) cpmglob(optind,argc,argv,&root,&gargc,&gargv);
380 else cpmglob(0,1,star,&root,&gargc,&gargv);
381 if (style==1) olddir(gargv,gargc);
382 else if (style==2) oldddir(gargv,gargc,&root);
383 else if (style==3) old3dir(gargv,gargc,&root);
384 else if (style==5) lsattr(gargv, gargc, &root);
385 else ls(gargv,gargc,&root,style==4,changetime,inode);