SCP: Add support for ~/ references to user home directory when opening files
This commit is contained in:
parent
06cedc7cbe
commit
076c1ef094
3 changed files with 108 additions and 34 deletions
34
scp.c
34
scp.c
|
@ -233,13 +233,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <direct.h>
|
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
#if defined(HAVE_DLOPEN) /* Dynamic Readline support */
|
#if defined(HAVE_DLOPEN) /* Dynamic Readline support */
|
||||||
|
@ -6870,7 +6866,7 @@ GET_SWITCHES (cptr); /* get switches */
|
||||||
gbuf[sizeof(gbuf)-1] = '\0';
|
gbuf[sizeof(gbuf)-1] = '\0';
|
||||||
strlcpy (gbuf, cptr, sizeof(gbuf));
|
strlcpy (gbuf, cptr, sizeof(gbuf));
|
||||||
sim_trim_endspc(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 sim_messagef(SCPE_IOERR, "Unable to directory change to: %s\n", gbuf);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -6962,9 +6958,9 @@ if (*cptr == '\0')
|
||||||
else {
|
else {
|
||||||
if ((WildName[strlen (WildName) - 1] == '/') ||
|
if ((WildName[strlen (WildName) - 1] == '/') ||
|
||||||
(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));
|
strlcat (WildName, "/*", sizeof (WildName));
|
||||||
r = sim_dir_scan (cptr, sim_dir_entry, &dir_state);
|
r = sim_dir_scan (cptr, sim_dir_entry, &dir_state);
|
||||||
sim_dir_entry (NULL, NULL, 0, NULL, &dir_state); /* output summary */
|
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] == '\\'))
|
if ((dname[strlen (dname) - 1] == '/') || (dname[strlen (dname) - 1] == '\\'))
|
||||||
dname[strlen (dname) - 1] = '\0';
|
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, '\\') ? "\\" : "/"));
|
const char *dslash = (strrchr (dname, '/') ? "/" : (strrchr (dname, '\\') ? "\\" : "/"));
|
||||||
|
|
||||||
dname[sizeof (dname) - 1] = '\0';
|
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';
|
path[strlen (path) - 1] = '\0';
|
||||||
while ((c = strstr (path, "//")))
|
while ((c = strstr (path, "//")))
|
||||||
memmove (c, c + 1, strlen (c + 1) + 1); /* clean out any empty directories // */
|
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);
|
return sim_messagef (SCPE_OK, "directory %s already exists\n", path);
|
||||||
c = path;
|
c = path;
|
||||||
while ((c = strchr (c, '/'))) {
|
while ((c = strchr (c, '/'))) {
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
if (!stat (path, &filestat)) {
|
if (!sim_stat (path, &filestat)) {
|
||||||
if (filestat.st_mode & S_IFDIR) {
|
if (filestat.st_mode & S_IFDIR) {
|
||||||
*c = '/'; /* restore / */
|
*c = '/'; /* restore / */
|
||||||
++c;
|
++c;
|
||||||
|
@ -7207,24 +7203,12 @@ while ((c = strchr (c, '/'))) {
|
||||||
}
|
}
|
||||||
return sim_messagef (SCPE_ARG, "%s is not a directory\n", path);
|
return sim_messagef (SCPE_ARG, "%s is not a directory\n", path);
|
||||||
}
|
}
|
||||||
if (
|
if (sim_mkdir (path))
|
||||||
#if defined(_WIN32)
|
|
||||||
mkdir (path)
|
|
||||||
#else
|
|
||||||
mkdir (path, 0777)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
return sim_messagef (SCPE_ARG, "Can't create directory: %s - %s\n", path, strerror (errno));
|
return sim_messagef (SCPE_ARG, "Can't create directory: %s - %s\n", path, strerror (errno));
|
||||||
*c = '/'; /* restore / */
|
*c = '/'; /* restore / */
|
||||||
++c;
|
++c;
|
||||||
}
|
}
|
||||||
if (
|
if (sim_mkdir (path))
|
||||||
#if defined(_WIN32)
|
|
||||||
mkdir (path)
|
|
||||||
#else
|
|
||||||
mkdir (path, 0777)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
return sim_messagef (SCPE_ARG, "Can't create directory: %s - %s\n", path, strerror (errno));
|
return sim_messagef (SCPE_ARG, "Can't create directory: %s - %s\n", path, strerror (errno));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -7234,7 +7218,7 @@ t_stat rmdir_cmd (int32 flg, CONST char *cptr)
|
||||||
GET_SWITCHES (cptr); /* get switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if ((!cptr) || (*cptr == '\0'))
|
if ((!cptr) || (*cptr == '\0'))
|
||||||
return sim_messagef (SCPE_2FARG, "Must specify a directory\n");
|
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 sim_messagef (SCPE_ARG, "Can't remove directory: %s - %s\n", cptr, strerror (errno));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
102
sim_fio.c
102
sim_fio.c
|
@ -248,19 +248,90 @@ if ((0 != fstat (fileno (fp), &statb)) ||
|
||||||
return TRUE;
|
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 <direct.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#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 */
|
/* OS-dependent routines */
|
||||||
|
|
||||||
/* Optimized file open */
|
/* Optimized file open */
|
||||||
|
|
||||||
FILE *sim_fopen (const char *file, const char *mode)
|
FILE *sim_fopen (const char *file, const char *mode)
|
||||||
{
|
{
|
||||||
|
char namebuf[PATH_MAX + 1];
|
||||||
|
|
||||||
|
_sim_expand_homedir (file, namebuf, sizeof (namebuf));
|
||||||
#if defined (VMS)
|
#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");
|
"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)
|
#elif (defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX)) && !defined (DONT_DO_LARGEFILE)
|
||||||
return fopen64 (file, mode);
|
return fopen64 (namebuf, mode);
|
||||||
#else
|
#else
|
||||||
return fopen (file, mode);
|
return fopen (namebuf, mode);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +463,11 @@ return szMsgBuffer;
|
||||||
|
|
||||||
t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool overwrite_existing)
|
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 SCPE_OK;
|
||||||
return sim_messagef (SCPE_ARG, "Error Copying '%s' to '%s': %s\n", source_file, dest_file, sim_get_os_error_text (GetLastError ()));
|
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) {
|
if (st == SCPE_OK) {
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
|
|
||||||
if (!stat (source_file, &statb)) {
|
if (!sim_stat (source_file, &statb)) {
|
||||||
struct utimbuf utim;
|
struct utimbuf utim;
|
||||||
|
|
||||||
utim.actime = statb.st_atime;
|
utim.actime = statb.st_atime;
|
||||||
|
@ -762,7 +837,9 @@ char chr;
|
||||||
const char *p;
|
const char *p;
|
||||||
char filesizebuf[32] = "";
|
char filesizebuf[32] = "";
|
||||||
char filedatetimebuf[32] = "";
|
char filedatetimebuf[32] = "";
|
||||||
|
char namebuf[PATH_MAX + 1];
|
||||||
|
|
||||||
|
/* Remove quotes if they're present */
|
||||||
if (((*filepath == '\'') || (*filepath == '"')) &&
|
if (((*filepath == '\'') || (*filepath == '"')) &&
|
||||||
(filepath[strlen (filepath) - 1] == *filepath)) {
|
(filepath[strlen (filepath) - 1] == *filepath)) {
|
||||||
size_t temp_size = 1 + strlen (filepath);
|
size_t temp_size = 1 + strlen (filepath);
|
||||||
|
@ -774,6 +851,12 @@ if (((*filepath == '\'') || (*filepath == '"')) &&
|
||||||
tempfilepath[strlen (tempfilepath) - 1] = '\0';
|
tempfilepath[strlen (tempfilepath) - 1] = '\0';
|
||||||
filepath = tempfilepath;
|
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] == ':') ||
|
if ((filepath[1] == ':') ||
|
||||||
(filepath[0] == '/') ||
|
(filepath[0] == '/') ||
|
||||||
(filepath[0] == '\\')){
|
(filepath[0] == '\\')){
|
||||||
|
@ -785,7 +868,7 @@ if ((filepath[1] == ':') ||
|
||||||
}
|
}
|
||||||
strcpy (fullpath, filepath);
|
strcpy (fullpath, filepath);
|
||||||
}
|
}
|
||||||
else {
|
else { /* Need to prepend current directory */
|
||||||
char dir[PATH_MAX+1] = "";
|
char dir[PATH_MAX+1] = "";
|
||||||
char *wd = sim_getcwd(dir, sizeof (dir));
|
char *wd = sim_getcwd(dir, sizeof (dir));
|
||||||
|
|
||||||
|
@ -837,7 +920,8 @@ if (ext == NULL)
|
||||||
tot_size = 0;
|
tot_size = 0;
|
||||||
if (*parts == '\0') /* empty part specifier means strip only quotes */
|
if (*parts == '\0') /* empty part specifier means strip only quotes */
|
||||||
tot_size = strlen (tempfilepath);
|
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 stat filestat;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
||||||
|
@ -919,7 +1003,7 @@ WIN32_FIND_DATAA File;
|
||||||
struct stat filestat;
|
struct stat filestat;
|
||||||
char WildName[PATH_MAX + 1];
|
char WildName[PATH_MAX + 1];
|
||||||
|
|
||||||
strlcpy (WildName, cptr, sizeof(WildName));
|
_sim_expand_homedir (cptr, WildName, sizeof (WildName));
|
||||||
cptr = WildName;
|
cptr = WildName;
|
||||||
sim_trim_endspc (WildName);
|
sim_trim_endspc (WildName);
|
||||||
if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
|
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 (DirName, 0, sizeof(DirName));
|
||||||
memset (WholeName, 0, sizeof(WholeName));
|
memset (WholeName, 0, sizeof(WholeName));
|
||||||
memset (MatchName, 0, sizeof(MatchName));
|
memset (MatchName, 0, sizeof(MatchName));
|
||||||
strlcpy (WildName, cptr, sizeof(WildName));
|
_sim_expand_homedir (cptr, WildName, sizeof (WildName));
|
||||||
cptr = WildName;
|
cptr = WildName;
|
||||||
sim_trim_endspc (WildName);
|
sim_trim_endspc (WildName);
|
||||||
c = sim_filepath_parts (cptr, "f");
|
c = sim_filepath_parts (cptr, "f");
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define FLIP_SIZE (1 << 16) /* flip buf size */
|
#define FLIP_SIZE (1 << 16) /* flip buf size */
|
||||||
#define fxread(a,b,c,d) sim_fread (a, b, c, d)
|
#define fxread(a,b,c,d) sim_fread (a, b, c, d)
|
||||||
#define fxwrite(a,b,c,d) sim_fwrite (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_ftell (FILE *st);
|
||||||
t_offset sim_fsize_ex (FILE *fptr);
|
t_offset sim_fsize_ex (FILE *fptr);
|
||||||
t_offset sim_fsize_name_ex (const char *fname);
|
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);
|
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_filepath_parts (const char *pathname, const char *parts);
|
||||||
char *sim_getcwd (char *buf, size_t buf_size);
|
char *sim_getcwd (char *buf, size_t buf_size);
|
||||||
|
|
Loading…
Add table
Reference in a new issue