From 076c1ef094d4b45c9651a32813dca4670dd8d2aa Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sat, 6 Mar 2021 14:04:54 -0800 Subject: [PATCH] SCP: Add support for ~/ references to user home directory when opening files --- scp.c | 34 +++++------------- sim_fio.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++----- sim_fio.h | 6 ++++ 3 files changed, 108 insertions(+), 34 deletions(-) diff --git a/scp.c b/scp.c index 8d9addec..d46585d4 100644 --- a/scp.c +++ b/scp.c @@ -233,13 +233,9 @@ #include #include #if defined(_WIN32) -#include #include #include -#else -#include #endif -#include #include #if defined(HAVE_DLOPEN) /* Dynamic Readline support */ @@ -6870,7 +6866,7 @@ GET_SWITCHES (cptr); /* get switches */ gbuf[sizeof(gbuf)-1] = '\0'; strlcpy (gbuf, cptr, sizeof(gbuf)); sim_trim_endspc(gbuf); -if (chdir(gbuf) != 0) +if (sim_chdir(gbuf) != 0) return sim_messagef(SCPE_IOERR, "Unable to directory change to: %s\n", gbuf); return SCPE_OK; } @@ -6962,9 +6958,9 @@ if (*cptr == '\0') else { if ((WildName[strlen (WildName) - 1] == '/') || (WildName[strlen (WildName) - 1] == '\\')) - WildName[strlen (WildName) - 1] = '\0'; + strlcat (WildName, ".", sizeof (WildName)); } -if ((!stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR)) +if ((!sim_stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR)) strlcat (WildName, "/*", sizeof (WildName)); r = sim_dir_scan (cptr, sim_dir_entry, &dir_state); sim_dir_entry (NULL, NULL, 0, NULL, &dir_state); /* output summary */ @@ -7129,7 +7125,7 @@ sprintf (FullPath, "%s%s", directory, filename); if ((dname[strlen (dname) - 1] == '/') || (dname[strlen (dname) - 1] == '\\')) dname[strlen (dname) - 1] = '\0'; -if ((!stat (dname, &deststat)) && (deststat.st_mode & S_IFDIR)) { +if ((!sim_stat (dname, &deststat)) && (deststat.st_mode & S_IFDIR)) { const char *dslash = (strrchr (dname, '/') ? "/" : (strrchr (dname, '\\') ? "\\" : "/")); dname[sizeof (dname) - 1] = '\0'; @@ -7194,12 +7190,12 @@ if (path[strlen (path) - 1] == '/') /* trim any trailing / from the path */ path[strlen (path) - 1] = '\0'; while ((c = strstr (path, "//"))) memmove (c, c + 1, strlen (c + 1) + 1); /* clean out any empty directories // */ -if ((!stat (path, &filestat)) && (filestat.st_mode & S_IFDIR)) +if ((!sim_stat (path, &filestat)) && (filestat.st_mode & S_IFDIR)) return sim_messagef (SCPE_OK, "directory %s already exists\n", path); c = path; while ((c = strchr (c, '/'))) { *c = '\0'; - if (!stat (path, &filestat)) { + if (!sim_stat (path, &filestat)) { if (filestat.st_mode & S_IFDIR) { *c = '/'; /* restore / */ ++c; @@ -7207,24 +7203,12 @@ while ((c = strchr (c, '/'))) { } return sim_messagef (SCPE_ARG, "%s is not a directory\n", path); } - if ( -#if defined(_WIN32) - mkdir (path) -#else - mkdir (path, 0777) -#endif - ) + if (sim_mkdir (path)) return sim_messagef (SCPE_ARG, "Can't create directory: %s - %s\n", path, strerror (errno)); *c = '/'; /* restore / */ ++c; } -if ( -#if defined(_WIN32) - mkdir (path) -#else - mkdir (path, 0777) -#endif - ) +if (sim_mkdir (path)) return sim_messagef (SCPE_ARG, "Can't create directory: %s - %s\n", path, strerror (errno)); return SCPE_OK; } @@ -7234,7 +7218,7 @@ t_stat rmdir_cmd (int32 flg, CONST char *cptr) GET_SWITCHES (cptr); /* get switches */ if ((!cptr) || (*cptr == '\0')) return sim_messagef (SCPE_2FARG, "Must specify a directory\n"); -if (rmdir (cptr)) +if (sim_rmdir (cptr)) return sim_messagef (SCPE_ARG, "Can't remove directory: %s - %s\n", cptr, strerror (errno)); return SCPE_OK; } diff --git a/sim_fio.c b/sim_fio.c index 41833701..fbd2b0e7 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -248,19 +248,90 @@ if ((0 != fstat (fileno (fp), &statb)) || return TRUE; } +static void _sim_expand_homedir (const char *file, char *dest, size_t dest_size) +{ +if (memcmp (file, "~/", 2) != 0) + strlcpy (dest, file, dest_size); +else { + char *cptr = getenv("HOME"); + char *cptr2; + + if (cptr == NULL) { + cptr = getenv("HOMEPATH"); + cptr2 = getenv("HOMEDRIVE"); + } + else + cptr2 = NULL; + if (cptr && (dest_size > strlen (cptr) + strlen (file) + 3)) + snprintf(dest, dest_size, "%s%s%s%s", cptr2 ? cptr2 : "", cptr, strchr (cptr, '/') ? "/" : "\\", file + 2); + else + strlcpy (dest, file, dest_size); + while ((strchr (dest, '\\') != NULL) && ((cptr = strchr (dest, '/')) != NULL)) + *cptr = '\\'; + } +} + +#if defined(_WIN32) +#include +#include +#include +#else +#include +#endif + +int sim_stat (const char *fname, struct stat *stat_str) +{ +char namebuf[PATH_MAX + 1]; + +_sim_expand_homedir (fname, namebuf, sizeof (namebuf)); +return stat (namebuf, stat_str); +} + +int sim_chdir(const char *path) +{ +char pathbuf[PATH_MAX + 1]; + +_sim_expand_homedir (path, pathbuf, sizeof (pathbuf)); +return chdir (pathbuf); +} + +int sim_mkdir(const char *path) +{ +char pathbuf[PATH_MAX + 1]; + +_sim_expand_homedir (path, pathbuf, sizeof (pathbuf)); +#if defined(_WIN32) +return mkdir (pathbuf); +#else +return mkdir (pathbuf, 0777); +#endif +} + +int sim_rmdir(const char *path) +{ +char pathbuf[PATH_MAX + 1]; + +_sim_expand_homedir (path, pathbuf, sizeof (pathbuf)); +return rmdir (pathbuf); +} + + /* OS-dependent routines */ /* Optimized file open */ FILE *sim_fopen (const char *file, const char *mode) { +char namebuf[PATH_MAX + 1]; + +_sim_expand_homedir (file, namebuf, sizeof (namebuf)); #if defined (VMS) -return fopen (file, mode, "ALQ=32", "DEQ=4096", +return fopen (namebuf, mode, "ALQ=32", "DEQ=4096", "MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm"); #elif (defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX)) && !defined (DONT_DO_LARGEFILE) -return fopen64 (file, mode); +return fopen64 (namebuf, mode); #else -return fopen (file, mode); +return fopen (namebuf, mode); #endif } @@ -392,7 +463,11 @@ return szMsgBuffer; t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool overwrite_existing) { -if (CopyFileA (source_file, dest_file, !overwrite_existing)) +char sourcename[PATH_MAX + 1], destname[PATH_MAX + 1]; + +_sim_expand_homedir (source_file, sourcename, sizeof (sourcename)); +_sim_expand_homedir (dest_file, destname, sizeof (destname)); +if (CopyFileA (sourcename, destname, !overwrite_existing)) return SCPE_OK; return sim_messagef (SCPE_ARG, "Error Copying '%s' to '%s': %s\n", source_file, dest_file, sim_get_os_error_text (GetLastError ())); } @@ -540,7 +615,7 @@ if (fOut) if (st == SCPE_OK) { struct stat statb; - if (!stat (source_file, &statb)) { + if (!sim_stat (source_file, &statb)) { struct utimbuf utim; utim.actime = statb.st_atime; @@ -762,7 +837,9 @@ char chr; const char *p; char filesizebuf[32] = ""; char filedatetimebuf[32] = ""; +char namebuf[PATH_MAX + 1]; +/* Remove quotes if they're present */ if (((*filepath == '\'') || (*filepath == '"')) && (filepath[strlen (filepath) - 1] == *filepath)) { size_t temp_size = 1 + strlen (filepath); @@ -774,6 +851,12 @@ if (((*filepath == '\'') || (*filepath == '"')) && tempfilepath[strlen (tempfilepath) - 1] = '\0'; filepath = tempfilepath; } + +/* Expand ~/ home directory */ +_sim_expand_homedir (filepath, namebuf, sizeof (namebuf)); +filepath = namebuf; + +/* Check for full or current directory relative path */ if ((filepath[1] == ':') || (filepath[0] == '/') || (filepath[0] == '\\')){ @@ -785,7 +868,7 @@ if ((filepath[1] == ':') || } strcpy (fullpath, filepath); } -else { +else { /* Need to prepend current directory */ char dir[PATH_MAX+1] = ""; char *wd = sim_getcwd(dir, sizeof (dir)); @@ -837,7 +920,8 @@ if (ext == NULL) tot_size = 0; if (*parts == '\0') /* empty part specifier means strip only quotes */ tot_size = strlen (tempfilepath); -if (strchr (parts, 't') || strchr (parts, 'z')) { +if (strchr (parts, 't') || /* modification time or */ + strchr (parts, 'z')) { /* or size requested? */ struct stat filestat; struct tm *tm; @@ -919,7 +1003,7 @@ WIN32_FIND_DATAA File; struct stat filestat; char WildName[PATH_MAX + 1]; -strlcpy (WildName, cptr, sizeof(WildName)); +_sim_expand_homedir (cptr, WildName, sizeof (WildName)); cptr = WildName; sim_trim_endspc (WildName); if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) { @@ -982,7 +1066,7 @@ char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1], Mat memset (DirName, 0, sizeof(DirName)); memset (WholeName, 0, sizeof(WholeName)); memset (MatchName, 0, sizeof(MatchName)); -strlcpy (WildName, cptr, sizeof(WildName)); +_sim_expand_homedir (cptr, WildName, sizeof (WildName)); cptr = WildName; sim_trim_endspc (WildName); c = sim_filepath_parts (cptr, "f"); diff --git a/sim_fio.h b/sim_fio.h index a632e5fd..ba7c23a3 100644 --- a/sim_fio.h +++ b/sim_fio.h @@ -37,6 +37,8 @@ extern "C" { #endif +#include + #define FLIP_SIZE (1 << 16) /* flip buf size */ #define fxread(a,b,c,d) sim_fread (a, b, c, d) #define fxwrite(a,b,c,d) sim_fwrite (a, b, c, d) @@ -70,6 +72,10 @@ uint32 sim_fsize_name (const char *fname); t_offset sim_ftell (FILE *st); t_offset sim_fsize_ex (FILE *fptr); t_offset sim_fsize_name_ex (const char *fname); +int sim_stat (const char *fname, struct stat *stat_str); +int sim_chdir(const char *path); +int sim_mkdir(const char *path); +int sim_rmdir(const char *path); t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool overwrite_existing); char *sim_filepath_parts (const char *pathname, const char *parts); char *sim_getcwd (char *buf, size_t buf_size);