Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 1715 → Rev 1716

/svarcom/trunk/cmd/dir.c
1,7 → 1,7
/* This file is part of the SvarCOM project and is published under the terms
* of the MIT license.
*
* Copyright (C) 2021-2022 Mateusz Viste
* Copyright (C) 2021-2024 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
56,6 → 56,26
#define WCOLWIDTH 15 /* width of a column in wide mode output */
 
 
/* a "tiny" DTA is a DTA that is stripped from bytes that are not needed for
* DIR operations */
_Packed struct TINYDTA {
/* char reserved[21];
unsigned char attr; */
unsigned short time_sec2:5;
unsigned short time_min:6;
unsigned short time_hour:5;
unsigned short date_dy:5;
unsigned short date_mo:4;
unsigned short date_yr:7;
unsigned long size;
/* char fname[13]; */
char fname[12];
};
 
/* max amount of DTAs that can be buffered (not using 65535 because fmalloc a bit of overhead space) */
#define MAX_DTA_BUFCOUNT (65500 / sizeof(struct TINYDTA))
 
 
/* fills freebytes with free bytes for drv (A=0, B=1, etc)
* returns DOS ERR code on failure */
static unsigned short cmd_dir_df(unsigned long *freebytes, unsigned char drv) {
157,11 → 177,27
}
 
 
/* compare attributes in a DTA node to mandatory and optional attributes. returns 1 on match, 0 otherwise */
static int filter_attribs(const struct DTA *dta, unsigned char attrfilter_must, unsigned char attrfilter_may) {
/* if mandatory attribs are requested, filter them now */
if ((attrfilter_must & dta->attr) != attrfilter_must) return(0);
 
/* if file contains attributes that are not allowed -> skip */
if ((~attrfilter_may & dta->attr) != 0) return(0);
 
return(1);
}
 
 
 
#define DIR_ATTR_DEFAULT (DOS_ATTR_RO | DOS_ATTR_DIR | DOS_ATTR_ARC)
 
static enum cmd_result cmd_dir(struct cmd_funcparam *p) {
const char *filespecptr = NULL;
struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */
struct DTA far *dtabuf = NULL; /* used to buffer results when sorting is enabled */
struct DTA far *dtabuf_root = NULL;
unsigned short dtabufcount = 0;
unsigned short i;
unsigned short availrows; /* counter of available rows on display (used for /P) */
unsigned short screenw = screen_getwidth();
174,6 → 210,12
unsigned char drv = 0;
unsigned char attrfilter_may = DIR_ATTR_DEFAULT;
unsigned char attrfilter_must = 0;
const char far *order = NULL; /* order string (like "GNE-SD"), this may come
either from the /O argument or from the
DIRCMD env variable (NULL = "no sort")
note 1: the '-' reverse relates only to
the letter that immediately follows it
note 2: '/O' is a shorthand for '/OGNE' */
 
#define DIR_FLAG_PAUSE 1
#define DIR_FLAG_RECUR 4
258,9 → 300,7
break;
case 'o':
case 'O':
/* TODO */
outputnl("/O NOT IMPLEMENTED YET");
return(CMD_FAIL);
order = arg+1;
break;
case 'p':
case 'P':
339,14 → 379,64
return(CMD_FAIL);
}
 
/* if sorting is involved, then let's buffer all results (and sort them) */
if (order != NULL) {
/* allocate a memory buffer - try several sizes until one succeeds */
unsigned short memsz[] = {65500, 32000, 16000, 8000, 4000, 2000, 0};
unsigned short max_dta_bufcount = 0;
for (i = 0; memsz[i] != 0; i++) {
dtabuf = _fmalloc(memsz[i]);
if (dtabuf != NULL) break;
}
 
if (dtabuf == NULL) {
nls_outputnl_doserr(8); /* out of memory */
return(CMD_FAIL);
}
 
/* remember the address so I can free it afterwards */
dtabuf_root = dtabuf;
 
/* compute the amount of DTAs I can buffer */
max_dta_bufcount = 1; //memsz[i] / sizeof(struct TINYDTA);
printf("max_dta_bufcount = %u\n", max_dta_bufcount);
 
do {
/* filter out files with uninteresting attributes */
if (filter_attribs(dta, attrfilter_must, attrfilter_may) == 0) continue;
 
_fmemcpy(&(dtabuf[dtabufcount]), ((char *)dta) + 22, sizeof(struct TINYDTA));
 
/* save attribs in sec field, otherwise zero it (this field is not
* displayed and dropping the attr field saves 2 bytes per entry) */
dtabuf[dtabufcount++].time_sec2 = (dta->attr & 31);
 
/* do I have any space left? */
if (dtabufcount == max_dta_bufcount) {
//outputnl("TOO MANY ENTRIES FOR SORTING! LIST IS UNSORTED");
break;
}
 
} while (findnext(dta) == 0);
 
/* sort the list - the tricky part is that my array is a far address while
* qsort works only with near pointers, so I have to use an ugly auxiliary
* table */
// qsort(dt); TODO
 
/* preload first entry */
_fmemcpy(((unsigned char *)dta) + 22, dtabuf, sizeof(struct TINYDTA));
dta->attr = dtabuf->time_sec2;
dtabuf++;
dtabufcount--;
}
 
wcolcount = 0; /* may be used for columns counting with wide mode */
 
do {
/* if mandatory attribs are requested, filter them now */
if ((attrfilter_must & dta->attr) != attrfilter_must) continue;
for (;;) {
 
/* if file contains attributes that are not allowed -> skip */
if ((~attrfilter_may & dta->attr) != 0) continue;
/* filter out attributes (skip if entry comes from buffer, then it was already veted) */
if (filter_attribs(dta, attrfilter_must, attrfilter_may) == 0) continue;
 
/* turn string lcase (/L) */
if (flags & DIR_FLAG_LCASE) _strlwr(dta->fname); /* OpenWatcom extension, probably does not care about NLS so results may be odd with non-A-Z characters... */
417,8 → 507,19
 
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
 
} while (findnext(dta) == 0);
/* take next entry, either from buf or disk */
if (dtabufcount > 0) {
/* preload first entry */
_fmemcpy(((unsigned char *)dta) + 22, dtabuf, sizeof(struct TINYDTA));
dta->attr = dtabuf->time_sec2;
dtabuf++;
dtabufcount--;
} else {
if (findnext(dta) != 0) break;
}
 
}
 
if (wcolcount != 0) {
outputnl(""); /* in wide mode make sure to end on a clear row */
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
452,5 → 553,8
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
}
 
/* free the buffer memory (if used) */
if (dtabuf_root != NULL) _ffree(dtabuf_root);
 
return(CMD_OK);
}
/svarcom/trunk/cmd.c
34,6 → 34,7
*/
 
#include <i86.h>
#include <malloc.h> /* _fmalloc() */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/svarcom/trunk/history.txt
8,6 → 8,7
 
=== ver 2024.2 (xx.xx.2024) ==================================================
 
- DIR command: added /O support
- command-line parsing modified to work around a DN bug. Thanks to bttr for
reporting the issue and to ECM for locating the root cause.
ref: https://github.com/SvarDOS/bugz/issues/67