Skip to content

Commit 4cce511

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 81fddb0 commit 4cce511

1 file changed

Lines changed: 45 additions & 4 deletions

File tree

‎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)