Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 78 additions & 7 deletions joe/b.c
Original file line number Diff line number Diff line change
Expand Up @@ -2569,15 +2569,42 @@ char *parsens(const char *s, off_t *skip, off_t *amnt, int *binary)
return n;
}

#ifndef __MSDOS__
#if defined(PATH_MAX) && PATH_MAX >= 4096
#define JOE_PATH_MAX PATH_MAX
#elif defined(MAXPATHLEN) && MAXPATHLEN >= 4096
#define JOE_PATH_MAX MAXPATHLEN
#else
#define JOE_PATH_MAX 4096
#endif

#if _POSIX_VERSION >= 200809L
static char *joe_realpath(const char *path)
{
char *buf = realpath(path, NULL);
char *ret = buf ? vsndup(NULL, 0, sz(buf)) : NULL;
free(buf);
return ret;
}
#else
static char *joe_realpath(const char *path)
{
char buf[JOE_PATH_MAX];
char *ret = realpath(path, buf);
return ret ? vsndup(NULL, 0, sz(ret)) : NULL;
}
#endif
#endif

/* Canonicalize file name: do ~ expansion */

char *canonical(char *n, int flags)
char *canonical(char *n, enum canflags flags)
{
ptrdiff_t y = 0;
#ifndef __MSDOS__
ptrdiff_t x;
char *s;
if (!(flags & CANFLAG_NORESTART)) {
char *s, *filepath;
if (flags & CANFLAG_RESTART) {
for (y = zlen(n); ; --y)
if (y <= 2) {
y = 0;
Expand All @@ -2587,7 +2614,7 @@ char *canonical(char *n, int flags)
break;
}
}
if (n[y] == '~') {
if (flags & CANFLAG_TILDE && n[y] == '~') {
for (x = y + 1; n[x] && n[x] != '/'; ++x) ;
if (n[x] == '/') {
if (x == y + 1) {
Expand Down Expand Up @@ -2617,6 +2644,32 @@ char *canonical(char *n, int flags)
}
}
}

if (flags & CANFLAG_FULLPATH) {
filepath = joe_realpath(n + y);
if (filepath) {
vsrm(n);
n = filepath;
} else {
x = zlen(n + y);
while (x > y && n[--x] != '/') ; /* chop off leafname */
if (x > y) {
n[x] = 0;
filepath = joe_realpath(n + y);
n[x++] = '/';
} else {
filepath = joe_realpath(".");
}
if (filepath) {
if (filepath[sLen(filepath) - 1] != '/')
filepath = vsncpy(sv(filepath), "/", 1);
filepath = vsncpy(sv(filepath), sz(n+x));
vsrm(n);
n = filepath;
y = 0;
}
}
}
#endif
if (y) {
char *z = vsncpy(NULL, 0, n + y, zlen(n + y));
Expand All @@ -2626,6 +2679,12 @@ char *canonical(char *n, int flags)
return n;
}

char *canonical_copy(const char *s, enum canflags flags)
{
char *sp = (char *)s;
return canonical(vsndup(NULL, 0, sz(sp)), flags);
}

static off_t euclid(off_t a, off_t b)
{
if (!a)
Expand Down Expand Up @@ -2995,6 +3054,7 @@ B *bload(const char *s)
B *bfind(const char *s)
{
B *b;
char *s_full = NULL;

if (!s || !s[0]) {
berror = -1;
Expand All @@ -3005,18 +3065,29 @@ B *bfind(const char *s)
b->er = berror;
return b;
}
for (b = bufs.link.next; b != &bufs; b = b->link.next)
if (b->name && !zcmp(s, b->name)) {

if (*s != '*')
s_full = canonical_copy(s, CANFLAG_TILDE | CANFLAG_FULLPATH);
for (b = bufs.link.next; b != &bufs; b = b->link.next) {
char *n_full = b->name ? canonical_copy(b->name, CANFLAG_TILDE | CANFLAG_FULLPATH) : NULL;

if (b->name && !zcmp(s_full ? s_full : s, n_full ? n_full : b->name)) {
if (!b->orphan)
++b->count; /* Assumes caller is going to put this in a window! */
else
b->orphan = 0;
berror = 0;
b->internal = 0;
return b;
if (n_full) vsrm(n_full);
goto ret;
}
if (n_full && n_full != b->name) vsrm(n_full);
}
b = bload(s); /* Returns count==1 */

ret:
b->internal = 0;
if (s_full && s_full != s) vsrm(s_full);
return b;
}

Expand Down
10 changes: 8 additions & 2 deletions joe/b.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,14 @@ int bsavefd(P *p, int fd, off_t size);

char *parsens(const char *s, off_t *skip, off_t *amnt, int *binary);

char *canonical(char *s, int flags);
#define CANFLAG_NORESTART 1 /* Support path restart feature */
enum canflags {
CANFLAG_RESTART = 1, /* path restart feature */
CANFLAG_TILDE = 2, /* tilde expansion */
CANFLAG_FULLPATH = 4, /* get the full path */
};

char *canonical(char *s, enum canflags flags);
char *canonical_copy(const char *s, enum canflags flags);

/* Get byte at pointer or return NO_MORE_DATA if pointer is at end of buffer */
int brc(P *p);
Expand Down
2 changes: 1 addition & 1 deletion joe/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ static char *open_configrc_file(JFILE **result, const char *sys, const char *pre
/* Absolute path given, don't add suffix (too confusing when user knows it's a file) */
vsrm(fullpath);
fullpath = vsncpy(NULL, 0, sz(name));
fullpath = canonical(fullpath, 0);
fullpath = canonical(fullpath, CANFLAG_RESTART | CANFLAG_TILDE | CANFLAG_FULLPATH);
f = jfopen(fullpath, "r");
if (f) {
*result = f;
Expand Down
8 changes: 4 additions & 4 deletions joe/pw.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ static int rtnpw(W *w)
p_goto_bol(bw->cursor);
s = brvs(bw->cursor, byte - bw->cursor->byte);

if (pw->file_prompt & PWFLAG_FILENAME)
s = canonical(s, 0); /* Tilde expansion and // restart */
else if (pw->file_prompt & PWFLAG_COMMAND)
s = canonical(s, CANFLAG_NORESTART); /* Tilde expansion only */
if (pw->file_prompt & PWFLAG_COMMAND)
s = canonical(s, CANFLAG_TILDE); /* Tilde expansion only */
else if (pw->file_prompt & PWFLAG_FILENAME)
s = canonical(s, CANFLAG_RESTART | CANFLAG_TILDE); /* Tilde expansion and // restart */

/* Save text into history buffer */
if (pw->hist) {
Expand Down
2 changes: 1 addition & 1 deletion joe/pw.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct pw {
ptrdiff_t promptofst; /* Prompt scroll offset */
B *hist; /* History buffer */
void *object; /* Object */
bool file_prompt; /* Set if this is a file name prompt, so do ~ expansion */
int file_prompt; /* Set if this is a file name prompt, so do ~ expansion */
};

/* BW *wmkpw(BW *bw,char *prompt,int (*func)(),char *huh,int (*abrt)(),
Expand Down
2 changes: 1 addition & 1 deletion joe/tab.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static int get_entries(TAB *tab, ino_t prv)
int only_cmds = 0;

tmp = vsncpy(NULL,0,sv(tab->path));
tmp = canonical(tmp, 0);
tmp = canonical(tmp, CANFLAG_RESTART);

if (chpwd(tmp)) {
vsrm(tmp);
Expand Down
4 changes: 2 additions & 2 deletions joe/uerror.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ static int parseit(struct charmap *map,const char *s, off_t row,
if (current_dir && *name != '/') {
t = vsncpy(NULL, 0, sv(current_dir));
t = vsncpy(sv(t), sv(name));
t = canonical(t, CANFLAG_NORESTART);
t = canonical(t, CANFLAG_FULLPATH);
vsrm(name);
} else {
t = name;
Expand Down Expand Up @@ -646,7 +646,7 @@ int ujump(W *w, int k)
fullname = vsncpy(NULL, 0, sv(curd));
fullname = vsncpy(sv(fullname), sv(name));
vsrm(name);
name = canonical(fullname, CANFLAG_NORESTART);
name = canonical(fullname, CANFLAG_FULLPATH);
if (name && line != -1) {
ERROR *er = srcherr(bw, name, line);
uprevw(bw->parent, 0);
Expand Down
9 changes: 6 additions & 3 deletions joe/ufile.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ static int backup(BW *bw)

if (backpath) {
char *t = vsncpy(NULL,0,sz(backpath));
t = canonical(t, CANFLAG_NORESTART);
t = canonical(t, CANFLAG_TILDE | CANFLAG_FULLPATH);
joe_snprintf_2(name, SIZEOF(name), "%s/%s", t, namepart(tmp, SIZEOF(tmp), bw->b->name));
vsrm(t);
} else {
Expand All @@ -207,7 +207,7 @@ static int backup(BW *bw)
/* Create backup file name */
if (backpath) {
char *t = vsncpy(NULL, 0, sz(backpath));
t = canonical(t, CANFLAG_NORESTART);
t = canonical(t, CANFLAG_TILDE | CANFLAG_FULLPATH);
mkpath(t);
joe_snprintf_3(name, SIZEOF(name), "%s/%s%s", t, namepart(tmp, SIZEOF(tmp), dequote(bw->b->name)), backup_file_suffix);
vsrm(t);
Expand Down Expand Up @@ -480,8 +480,10 @@ static int dosave1(W *w, char *s, void *object, int *notify)
req->name = s;

if (s[0] != '!' && !(s[0] == '>' && s[1] == '>')) {
char *cname = bw->b->name ? canonical_copy(bw->b->name, CANFLAG_TILDE|CANFLAG_FULLPATH) : NULL;
/* It's a normal file: not a pipe or append */
if (!bw->b->name || zcmp(s, bw->b->name)) {
if (!cname || (zcmp(s, cname) && zcmp(s, bw->b->name))) {
vsrm(cname);
/* Newly named file or name is different than buffer */
f = open(dequote(s), O_RDONLY);
if (f != -1) {
Expand All @@ -493,6 +495,7 @@ static int dosave1(W *w, char *s, void *object, int *notify)
}
}
else {
vsrm(cname);
/* We're saving a newer version of the same file */
if (check_mod(bw->b)) {
req->message = joe_gettext(_("File on disk is newer. Overwrite (y,n,%{abort})? "));
Expand Down
Loading