aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Arun Prakash Jana <engineerarun@gmail.com>2019-11-20 01:28:11 +0530
committerGravatar Arun Prakash Jana <engineerarun@gmail.com>2019-11-20 01:28:11 +0530
commit3a9def25d815dae7a7db658d2383004417116fb6 (patch)
treef99d4caf81f236ffcdc336a81775886010268c7c
parent9729b1f5a60d612e173695f3e3a997a44f5d7a94 (diff)
downloadnnn-3a9def25d815dae7a7db658d2383004417116fb6.tar.gz
Create new files and dirs with parent (like mkdir -p)
-rw-r--r--README.md2
-rw-r--r--src/nnn.c67
2 files changed, 62 insertions, 7 deletions
diff --git a/README.md b/README.md
index e2c9adf..5bb80be 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ Add to that an awesome [Wiki](https://github.com/jarun/nnn/wiki)!
- Cross-dir file/all/range selection
- Batch rename selection or dir entries
- Copy (as), move (as), delete, archive, link selection
- - Create, rename, duplicate files and dirs
+ - Create (with parents), rename, duplicate (anywhere) files and dirs
- Spawn a shell, run apps, run commands, execute file
- Lock terminal (needs a locker)
- Minimal deps, minimal config
diff --git a/src/nnn.c b/src/nnn.c
index ff3fe11..341a78e 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -1317,6 +1317,59 @@ static void xrm(char *path)
}
}
+/* Create non-existent parents and a file or dir */
+static bool xmkentryp(char* path, bool dir)
+{
+ char* p = path;
+ char *slash = path;
+
+ if (!p || !*p)
+ return FALSE;
+
+ /* Skip the first '/' */
+ ++p;
+
+ while (*p != '\0') {
+ if (*p == '/') {
+ slash = p;
+ *p = '\0';
+ } else {
+ ++p;
+ continue;
+ }
+
+ /* Create folder from path to '\0' inserted at p */
+ if (mkdir(path, 0777) == -1 && errno != EEXIST) {
+ DPRINTF_S("mkdir1 fail");
+ DPRINTF_S(strerror(errno));
+ *slash = '/';
+ return FALSE;
+ }
+
+ /* Restore path */
+ *slash = '/';
+ ++p;
+ }
+
+ if (dir) {
+ if(mkdir(path, 0777) == -1 && errno != EEXIST) {
+ DPRINTF_S("mkdir2 fail");
+ DPRINTF_S(strerror(errno));
+ return FALSE;
+ }
+ } else {
+ int fd = open(path, O_CREAT, 0666);
+ if (fd == -1 && errno != EEXIST) {
+ DPRINTF_S("open fail");
+ DPRINTF_S(strerror(errno));
+ return FALSE;
+ } else
+ close(fd);
+ }
+
+ return TRUE;
+}
+
static uint lines_in_file(int fd, char *buf, size_t buflen)
{
ssize_t len;
@@ -4834,7 +4887,8 @@ nochange:
break;
/* Allow only relative, same dir paths */
- if (tmp[0] == '/' || xstrcmp(xbasename(tmp), tmp) != 0) {
+ if (tmp[0] == '/'
+ || ((r != 'f' && r != 'd') && (xstrcmp(xbasename(tmp), tmp) != 0))) {
printwait(messages[STR_INPUT_ID], &presel);
goto nochange;
}
@@ -4929,11 +4983,12 @@ nochange:
} else {
/* Check if it's a dir or file */
if (r == 'f') {
- r = openat(fd, tmp, O_CREAT, 0666);
- close(r);
- } else if (r == 'd')
- r = mkdirat(fd, tmp, 0777);
- else if (r == 's' || r == 'h') {
+ mkpath(path, tmp, newpath);
+ r = xmkentryp(newpath, FALSE);
+ } else if (r == 'd') {
+ mkpath(path, tmp, newpath);
+ r = xmkentryp(newpath, TRUE);
+ } else if (r == 's' || r == 'h') {
if (tmp[0] == '@' && tmp[1] == '\0')
tmp[0] = '\0';
r = xlink(tmp, path, newpath, &presel, r);