SCP: Add wild card support to DEL/RM and TYPE/CAT commands
This commit is contained in:
parent
cbf90e7d93
commit
c1f228f0b0
1 changed files with 167 additions and 86 deletions
251
scp.c
251
scp.c
|
@ -4986,28 +4986,30 @@ t_stat pwd_cmd (int32 flg, CONST char *cptr)
|
||||||
return show_cmd (0, "DEFAULT");
|
return show_cmd (0, "DEFAULT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (*DIR_ENTRY_CALLBACK)(const char *directory,
|
||||||
|
const char *filename,
|
||||||
|
t_offset FileSize,
|
||||||
|
const struct stat *filestat,
|
||||||
|
void *context);
|
||||||
|
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
|
|
||||||
t_stat dir_cmd (int32 flg, CONST char *cptr)
|
static t_stat sim_dir_scan (const char *cptr, DIR_ENTRY_CALLBACK entry, void *context)
|
||||||
{
|
{
|
||||||
HANDLE hFind;
|
HANDLE hFind;
|
||||||
WIN32_FIND_DATAA File;
|
WIN32_FIND_DATAA File;
|
||||||
struct stat filestat;
|
struct stat filestat;
|
||||||
char WildName[PATH_MAX + 1];
|
char WildName[PATH_MAX + 1];
|
||||||
|
|
||||||
if (*cptr == '\0')
|
|
||||||
cptr = "./*";
|
|
||||||
if ((!stat (cptr, &filestat)) && (filestat.st_mode & S_IFDIR)) {
|
if ((!stat (cptr, &filestat)) && (filestat.st_mode & S_IFDIR)) {
|
||||||
sprintf (WildName, "%s%c*", cptr, strchr (cptr, '/') ? '/' : '\\');
|
sprintf (WildName, "%s%c*", cptr, strchr (cptr, '/') ? '/' : '\\');
|
||||||
cptr = WildName;
|
cptr = WildName;
|
||||||
}
|
}
|
||||||
if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
|
if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
|
||||||
t_int64 FileSize, TotalSize = 0;
|
t_int64 FileSize;
|
||||||
int DirCount = 0, FileCount = 0;
|
|
||||||
char DirName[PATH_MAX + 1], FileName[PATH_MAX + 1];
|
char DirName[PATH_MAX + 1], FileName[PATH_MAX + 1];
|
||||||
const char *c;
|
const char *c;
|
||||||
char pathsep = '/';
|
char pathsep = '/';
|
||||||
struct tm *local;
|
|
||||||
|
|
||||||
GetFullPathNameA(cptr, sizeof(DirName), DirName, (char **)&c);
|
GetFullPathNameA(cptr, sizeof(DirName), DirName, (char **)&c);
|
||||||
c = strrchr(DirName, pathsep);
|
c = strrchr(DirName, pathsep);
|
||||||
|
@ -5022,39 +5024,17 @@ if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
|
||||||
else {
|
else {
|
||||||
getcwd(DirName, PATH_MAX);
|
getcwd(DirName, PATH_MAX);
|
||||||
}
|
}
|
||||||
sim_printf (" Directory of %s\n\n", DirName);
|
sprintf (&DirName[strlen (DirName)], "%c", pathsep);
|
||||||
do {
|
do {
|
||||||
FileSize = (((t_int64)(File.nFileSizeHigh)) << 32) | File.nFileSizeLow;
|
FileSize = (((t_int64)(File.nFileSizeHigh)) << 32) | File.nFileSizeLow;
|
||||||
sprintf (FileName, "%s%c%s", DirName, pathsep, File.cFileName);
|
sprintf (FileName, "%s%s", DirName, File.cFileName);
|
||||||
stat (FileName, &filestat);
|
stat (FileName, &filestat);
|
||||||
local = localtime (&filestat.st_mtime);
|
entry (DirName, File.cFileName, FileSize, &filestat, context);
|
||||||
sim_printf ("%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
|
|
||||||
if (filestat.st_mode & S_IFDIR) {
|
|
||||||
++DirCount;
|
|
||||||
sim_printf (" <DIR> ");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (filestat.st_mode & S_IFREG) {
|
|
||||||
++FileCount;
|
|
||||||
sim_print_val ((t_value) FileSize, 10, 17, PV_RCOMMA);
|
|
||||||
TotalSize += FileSize;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sim_printf ("%17s", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sim_printf (" %s\n", File.cFileName);
|
|
||||||
} while (FindNextFile (hFind, &File));
|
} while (FindNextFile (hFind, &File));
|
||||||
sim_printf ("%16d File(s)", FileCount);
|
|
||||||
sim_print_val ((t_value) TotalSize, 10, 15, PV_RCOMMA);
|
|
||||||
sim_printf (" bytes\n");
|
|
||||||
sim_printf ("%16d Dir(s)\n", DirCount);
|
|
||||||
FindClose (hFind);
|
FindClose (hFind);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
sim_printf ("Can't list files for %s\n", cptr);
|
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
}
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5069,7 +5049,7 @@ return SCPE_OK;
|
||||||
#endif
|
#endif
|
||||||
#endif /* defined (HAVE_GLOB) */
|
#endif /* defined (HAVE_GLOB) */
|
||||||
|
|
||||||
t_stat dir_cmd (int32 flg, CONST char *cptr)
|
static t_stat sim_dir_scan (const char *cptr, DIR_ENTRY_CALLBACK entry, void *context)
|
||||||
{
|
{
|
||||||
#if defined (HAVE_GLOB)
|
#if defined (HAVE_GLOB)
|
||||||
glob_t paths;
|
glob_t paths;
|
||||||
|
@ -5080,13 +5060,9 @@ struct stat filestat;
|
||||||
char *c;
|
char *c;
|
||||||
char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1];
|
char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1];
|
||||||
|
|
||||||
if (*cptr == '\0')
|
|
||||||
strcpy (WildName, "./*");
|
|
||||||
else
|
|
||||||
strcpy (WildName, cptr);
|
strcpy (WildName, cptr);
|
||||||
cptr = WildName;
|
cptr = WildName;
|
||||||
while (strlen(WildName) && sim_isspace(WildName[strlen(WildName)-1]))
|
sim_trim_endspc (WildName);
|
||||||
WildName[strlen(WildName)-1] = '\0';
|
|
||||||
if ((!stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR))
|
if ((!stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR))
|
||||||
strcat (WildName, "/*");
|
strcat (WildName, "/*");
|
||||||
if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../", 3))) {
|
if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../", 3))) {
|
||||||
|
@ -5097,8 +5073,7 @@ if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../"
|
||||||
#endif
|
#endif
|
||||||
strcat (WholeName, "/");
|
strcat (WholeName, "/");
|
||||||
strcat (WholeName, cptr);
|
strcat (WholeName, cptr);
|
||||||
while (strlen(WholeName) && sim_isspace(WholeName[strlen(WholeName)-1]))
|
sim_trim_endspc (WholeName);
|
||||||
WholeName[strlen(WholeName)-1] = '\0';
|
|
||||||
}
|
}
|
||||||
while ((c = strstr (WholeName, "/./")))
|
while ((c = strstr (WholeName, "/./")))
|
||||||
strcpy (c + 1, c + 3);
|
strcpy (c + 1, c + 3);
|
||||||
|
@ -5133,19 +5108,17 @@ dir = opendir(DirName[0] ? DirName : "/.");
|
||||||
if (dir) {
|
if (dir) {
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
#endif
|
#endif
|
||||||
t_offset FileSize, TotalSize = 0;
|
t_offset FileSize;
|
||||||
int DirCount = 0, FileCount = 0;
|
|
||||||
char FileName[PATH_MAX + 1];
|
char FileName[PATH_MAX + 1];
|
||||||
#if defined (HAVE_FNMATCH)
|
#if defined (HAVE_FNMATCH)
|
||||||
char *MatchName = 1 + strrchr (cptr, '/');;
|
char *MatchName = 1 + strrchr (cptr, '/');;
|
||||||
#endif
|
#endif
|
||||||
char *c;
|
char *p_name;
|
||||||
struct tm *local;
|
struct tm *local;
|
||||||
#if defined (HAVE_GLOB)
|
#if defined (HAVE_GLOB)
|
||||||
size_t i;
|
size_t i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sim_printf (" Directory of %s\n\n", DirName[0] ? DirName : "/");
|
|
||||||
#if defined (HAVE_GLOB)
|
#if defined (HAVE_GLOB)
|
||||||
for (i=0; i<paths.gl_pathc; i++) {
|
for (i=0; i<paths.gl_pathc; i++) {
|
||||||
sprintf (FileName, "%s", paths.gl_pathv[i]);
|
sprintf (FileName, "%s", paths.gl_pathv[i]);
|
||||||
|
@ -5157,35 +5130,10 @@ if (dir) {
|
||||||
#endif
|
#endif
|
||||||
sprintf (FileName, "%s/%s", DirName, ent->d_name);
|
sprintf (FileName, "%s/%s", DirName, ent->d_name);
|
||||||
#endif
|
#endif
|
||||||
|
p_name = FileName + strlen (DirName);
|
||||||
stat (FileName, &filestat);
|
stat (FileName, &filestat);
|
||||||
local = localtime (&filestat.st_mtime);
|
FileSize = (t_offset)((filestat.st_mode & S_IFDIR) ? 0 : sim_fsize_name_ex (FileName));
|
||||||
sim_printf ("%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
|
entry (DirName, p_name, FileSize, &filestat, context);
|
||||||
if (filestat.st_mode & S_IFDIR) {
|
|
||||||
++DirCount;
|
|
||||||
sim_printf (" <DIR> ");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (filestat.st_mode & S_IFREG) {
|
|
||||||
++FileCount;
|
|
||||||
FileSize = sim_fsize_name_ex (FileName);
|
|
||||||
sim_print_val ((t_value) FileSize, 10, 17, PV_RCOMMA);
|
|
||||||
TotalSize += FileSize;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sim_printf ("%17s", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c = strrchr (FileName, '/');
|
|
||||||
sim_printf (" %s\n", c ? c + 1 : FileName);
|
|
||||||
}
|
|
||||||
if (FileCount) {
|
|
||||||
sim_printf ("%16d File(s)", FileCount);
|
|
||||||
sim_print_val ((t_value) TotalSize, 10, 15, PV_RCOMMA);
|
|
||||||
sim_printf (" bytes\n");
|
|
||||||
sim_printf ("%16d Dir(s)\n", DirCount);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sim_printf ("File Not Found\n");
|
|
||||||
}
|
}
|
||||||
#if defined (HAVE_GLOB)
|
#if defined (HAVE_GLOB)
|
||||||
globfree (&paths);
|
globfree (&paths);
|
||||||
|
@ -5193,15 +5141,120 @@ if (dir) {
|
||||||
closedir (dir);
|
closedir (dir);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
sim_printf ("Can't list files for %s\n", cptr);
|
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
}
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !defined(_WIN32) */
|
#endif /* !defined(_WIN32) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char LastDir[PATH_MAX + 1];
|
||||||
|
t_offset TotalBytes;
|
||||||
|
int TotalDirs;
|
||||||
|
int TotalFiles;
|
||||||
|
int DirChanges;
|
||||||
|
int DirCount;
|
||||||
|
int FileCount;
|
||||||
|
t_offset ByteCount;
|
||||||
|
} DIR_CTX;
|
||||||
|
|
||||||
|
static void sim_dir_entry (const char *directory,
|
||||||
|
const char *filename,
|
||||||
|
t_offset FileSize,
|
||||||
|
const struct stat *filestat,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
DIR_CTX *ctx = (DIR_CTX *)context;
|
||||||
|
struct tm *local;
|
||||||
|
|
||||||
|
if ((directory == NULL) || (filename == NULL)) {
|
||||||
|
if (ctx->DirChanges > 1)
|
||||||
|
sim_printf (" Total Files Listed:\n");
|
||||||
|
if (ctx->DirChanges > 0) {
|
||||||
|
sim_printf ("%16d File(s) ", ctx->TotalFiles);
|
||||||
|
sim_print_val ((t_value) ctx->TotalBytes, 10, 17, PV_RCOMMA);
|
||||||
|
sim_printf (" bytes\n");
|
||||||
|
sim_printf ("%16d Dir(s)\n", ctx->TotalDirs);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp (ctx->LastDir, directory)) {
|
||||||
|
if (ctx->DirCount || ctx->FileCount) {
|
||||||
|
sim_printf ("%16d File(s) ", ctx->FileCount);
|
||||||
|
sim_print_val ((t_value) ctx->ByteCount, 10, 17, PV_RCOMMA);
|
||||||
|
sim_printf (" bytes\n");
|
||||||
|
ctx->ByteCount = ctx->DirCount = ctx->FileCount = 0;
|
||||||
|
sim_printf ("%16d Dir(s)\n", ctx->DirCount);
|
||||||
|
}
|
||||||
|
++ctx->DirChanges;
|
||||||
|
sim_printf (" Directory of %*.*s\n\n", strlen (directory) - 1, strlen (directory) - 1, directory);
|
||||||
|
strcpy (ctx->LastDir, directory);
|
||||||
|
}
|
||||||
|
local = localtime (&filestat->st_mtime);
|
||||||
|
sim_printf ("%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
|
||||||
|
if (filestat->st_mode & S_IFDIR) {
|
||||||
|
++ctx->DirCount;
|
||||||
|
++ctx->TotalDirs;
|
||||||
|
sim_printf (" <DIR> ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (filestat->st_mode & S_IFREG) {
|
||||||
|
++ctx->FileCount;
|
||||||
|
++ctx->TotalFiles;
|
||||||
|
sim_print_val ((t_value) FileSize, 10, 17, PV_RCOMMA);
|
||||||
|
ctx->ByteCount += FileSize;
|
||||||
|
ctx->TotalBytes += FileSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sim_printf ("%17s", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_printf (" %s\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat dir_cmd (int32 flg, CONST char *cptr)
|
||||||
|
{
|
||||||
|
DIR_CTX dir_state;
|
||||||
|
t_stat stat;
|
||||||
|
|
||||||
|
memset (&dir_state, 0, sizeof (dir_state));
|
||||||
|
if (*cptr == '\0')
|
||||||
|
cptr = "./*";
|
||||||
|
stat = sim_dir_scan (cptr, sim_dir_entry, &dir_state);
|
||||||
|
sim_dir_entry (NULL, NULL, 0, NULL, &dir_state); /* output summary */
|
||||||
|
if (stat != SCPE_OK)
|
||||||
|
return sim_messagef (SCPE_ARG, "File Not Found\n");
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
t_stat stat;
|
||||||
|
} TYPE_CTX;
|
||||||
|
|
||||||
|
static void sim_type_entry (const char *directory,
|
||||||
|
const char *filename,
|
||||||
|
t_offset FileSize,
|
||||||
|
const struct stat *filestat,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
TYPE_CTX *ctx = (TYPE_CTX *)context;
|
||||||
|
char FullPath[PATH_MAX + 1];
|
||||||
|
FILE *file;
|
||||||
|
char lbuf[4*CBUFSIZE];
|
||||||
|
|
||||||
|
sprintf (FullPath, "%s%s", directory, filename);
|
||||||
|
|
||||||
|
file = sim_fopen (FullPath, "r");
|
||||||
|
if (file == NULL) /* open failed? */
|
||||||
|
return;
|
||||||
|
sim_printf ("\n%s\n\n", FullPath);
|
||||||
|
lbuf[sizeof(lbuf)-1] = '\0';
|
||||||
|
while (fgets (lbuf, sizeof(lbuf)-1, file))
|
||||||
|
sim_printf ("%s", lbuf);
|
||||||
|
fclose (file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
t_stat type_cmd (int32 flg, CONST char *cptr)
|
t_stat type_cmd (int32 flg, CONST char *cptr)
|
||||||
{
|
{
|
||||||
|
@ -5214,8 +5267,16 @@ lbuf[sizeof(lbuf)-1] = '\0';
|
||||||
strncpy (lbuf, cptr, sizeof(lbuf)-1);
|
strncpy (lbuf, cptr, sizeof(lbuf)-1);
|
||||||
sim_trim_endspc(lbuf);
|
sim_trim_endspc(lbuf);
|
||||||
file = sim_fopen (lbuf, "r");
|
file = sim_fopen (lbuf, "r");
|
||||||
if (file == NULL) /* open failed? */
|
if (file == NULL) { /* open failed? */
|
||||||
return SCPE_OPENERR;
|
TYPE_CTX type_state;
|
||||||
|
t_stat stat;
|
||||||
|
|
||||||
|
memset (&type_state, 0, sizeof (type_state));
|
||||||
|
stat = sim_dir_scan (cptr, sim_type_entry, &type_state);
|
||||||
|
if (stat == SCPE_OK)
|
||||||
|
return SCPE_OK;
|
||||||
|
return sim_messagef (SCPE_OPENERR, "The system cannot find the file specified.\n");
|
||||||
|
}
|
||||||
lbuf[sizeof(lbuf)-1] = '\0';
|
lbuf[sizeof(lbuf)-1] = '\0';
|
||||||
while (fgets (lbuf, sizeof(lbuf)-1, file))
|
while (fgets (lbuf, sizeof(lbuf)-1, file))
|
||||||
sim_printf ("%s", lbuf);
|
sim_printf ("%s", lbuf);
|
||||||
|
@ -5223,18 +5284,38 @@ fclose (file);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
t_stat stat;
|
||||||
|
} DEL_CTX;
|
||||||
|
|
||||||
|
static void sim_delete_entry (const char *directory,
|
||||||
|
const char *filename,
|
||||||
|
t_offset FileSize,
|
||||||
|
const struct stat *filestat,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
DEL_CTX *ctx = (DEL_CTX *)context;
|
||||||
|
char FullPath[PATH_MAX + 1];
|
||||||
|
|
||||||
|
sprintf (FullPath, "%s%s", directory, filename);
|
||||||
|
|
||||||
|
if (!unlink (FullPath))
|
||||||
|
return;
|
||||||
|
ctx->stat = sim_messagef (SCPE_ARG, "%s\n", strerror (errno));
|
||||||
|
}
|
||||||
|
|
||||||
t_stat delete_cmd (int32 flg, CONST char *cptr)
|
t_stat delete_cmd (int32 flg, CONST char *cptr)
|
||||||
{
|
{
|
||||||
char lbuf[4*CBUFSIZE];
|
DEL_CTX del_state;
|
||||||
|
t_stat stat;
|
||||||
|
|
||||||
if ((!cptr) || (*cptr == 0))
|
if ((!cptr) || (*cptr == 0))
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
lbuf[sizeof(lbuf)-1] = '\0';
|
memset (&del_state, 0, sizeof (del_state));
|
||||||
strncpy (lbuf, cptr, sizeof(lbuf)-1);
|
stat = sim_dir_scan (cptr, sim_delete_entry, &del_state);
|
||||||
sim_trim_endspc(lbuf);
|
if (stat == SCPE_OK)
|
||||||
if (!unlink (lbuf))
|
return del_state.stat;
|
||||||
return SCPE_OK;
|
return sim_messagef (SCPE_ARG, "No such file or directory: %s\n", cptr);
|
||||||
return sim_messagef (SCPE_ARG, "%s\n", strerror (errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Breakpoint commands */
|
/* Breakpoint commands */
|
||||||
|
|
Loading…
Add table
Reference in a new issue