SCP: Add wild card support to DEL/RM and TYPE/CAT commands

This commit is contained in:
Mark Pizzolato 2017-02-19 13:57:03 -08:00
parent cbf90e7d93
commit c1f228f0b0

251
scp.c
View file

@ -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 */