Skip to content

Commit 4a61e89

Browse files
committed
Make ancestor directories before writing htoprc
... and don't create config directories when reading the htop config. The new subroutine for creating directories can also work with custom paths specified in HTOPRC environment variable. Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
1 parent ac1f59c commit 4a61e89

File tree

1 file changed

+45
-4
lines changed

1 file changed

+45
-4
lines changed

Settings.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,43 @@ static bool Settings_read(Settings* this, const char* fileName, const Machine* h
563563
return didReadAny;
564564
}
565565

566+
static int makeAncestorDirectories(char* filePath) {
567+
// The caller is expected to set the umask before calling this function.
568+
// In particular, if the umask contains S_IWUSR or S_IXUSR bit then the
569+
// making of subdirectories within the ancestor can fail.
570+
571+
// 0755 is the maximum permission we can give to directories at this phase.
572+
const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
573+
574+
bool hasDirectory = false;
575+
int savedErr = errno;
576+
577+
char *p = filePath;
578+
while (true) {
579+
while (*p == '/')
580+
p++;
581+
582+
while (*p && *p != '/')
583+
p++;
584+
585+
if (!*p)
586+
break;
587+
588+
*p = '\0';
589+
bool ok = !mkdir(filePath, mode);
590+
*p = '/';
591+
if (ok) {
592+
hasDirectory = true;
593+
errno = savedErr;
594+
} else if (hasDirectory) {
595+
return -errno;
596+
}
597+
// Try creating directories in the lower levels. It's possible for
598+
// mkdir() to succeed in a lower level while an error happens earlier.
599+
}
600+
return 0;
601+
}
602+
566603
typedef ATTR_FORMAT(printf, 2, 3) int (*OutputFunc)(FILE*, const char*,...);
567604

568605
static void writeFields(OutputFunc of, FILE* fp,
@@ -649,9 +686,15 @@ int Settings_write(const Settings* this, bool onCrash) {
649686
} else if (!this->writeConfig) {
650687
return 0;
651688
} else {
652-
/* create tempfile with mode 0600 */
653-
mode_t cur_umask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
689+
// Prepare temp filename
654690
xAsprintf(&tmpFilename, "%s.tmp.XXXXXX", this->filename);
691+
692+
// Create ancestor directories with mode 0700
693+
mode_t cur_umask = umask(S_IRWXG | S_IRWXO);
694+
makeAncestorDirectories(tmpFilename);
695+
696+
// Create temp file with mode 0600
697+
umask(S_IXUSR | S_IRWXG | S_IRWXO);
655698
int fdtmp = mkstemp(tmpFilename);
656699
umask(cur_umask);
657700
if (fdtmp == -1) {
@@ -851,8 +894,6 @@ Settings* Settings_new(const Machine* host, Hashtable* dynamicMeters, Hashtable*
851894
configDir = String_cat(home, CONFIGDIR);
852895
htopDir = String_cat(home, CONFIGDIR "/htop");
853896
}
854-
(void) mkdir(configDir, 0700);
855-
(void) mkdir(htopDir, 0700);
856897
free(htopDir);
857898
free(configDir);
858899

0 commit comments

Comments
 (0)