Skip to content
Closed
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
59 changes: 48 additions & 11 deletions Settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,43 @@ static bool Settings_read(Settings* this, const char* fileName, const Machine* h
return didReadAny;
}

static int makeAncestorDirectories(char* filePath) {
// The caller is expected to set the umask before calling this function.
// In particular, if the umask contains S_IWUSR or S_IXUSR bit then the
// making of subdirectories within the ancestor can fail.

// 0755 is the maximum permission we can give to directories at this phase.
const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;

bool hasDirectory = false;
int savedErr = errno;

char *p = filePath;
while (true) {
while (*p == '/')
p++;

while (*p && *p != '/')
p++;

if (!*p)
break;

*p = '\0';
bool ok = !mkdir(filePath, mode);
*p = '/';
if (ok) {
hasDirectory = true;
errno = savedErr;
} else if (hasDirectory) {
return -errno;
}
// Try creating directories in the lower levels. It's possible for
// mkdir() to succeed in a lower level while an error happens earlier.
}
return 0;
}

typedef ATTR_FORMAT(printf, 2, 3) int (*OutputFunc)(FILE*, const char*,...);

static void writeFields(OutputFunc of, FILE* fp,
Expand Down Expand Up @@ -649,9 +686,15 @@ int Settings_write(const Settings* this, bool onCrash) {
} else if (!this->writeConfig) {
return 0;
} else {
/* create tempfile with mode 0600 */
mode_t cur_umask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
xAsprintf(&tmpFilename, "%s.tmp.XXXXXX", this->filename);
// Prepare temp filename
tmpFilename = String_cat(this->filename, ".tmp.XXXXXX");

// Create ancestor directories with mode 0700
mode_t cur_umask = umask(S_IRWXG | S_IRWXO);
makeAncestorDirectories(tmpFilename);

// Create temp file with mode 0600
umask(S_IXUSR | S_IRWXG | S_IRWXO);
int fdtmp = mkstemp(tmpFilename);
umask(cur_umask);
if (fdtmp == -1) {
Expand All @@ -660,6 +703,7 @@ int Settings_write(const Settings* this, bool onCrash) {
}
fp = fdopen(fdtmp, "w");
if (!fp) {
close(fdtmp);
free(tmpFilename);
return -errno;
}
Expand Down Expand Up @@ -839,21 +883,14 @@ Settings* Settings_new(const Machine* host, Hashtable* dynamicMeters, Hashtable*
home = (pw && pw->pw_dir && pw->pw_dir[0] == '/') ? pw->pw_dir : "";
}
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
char* configDir = NULL;
char* htopDir = NULL;
if (xdgConfigHome && xdgConfigHome[0] == '/') {
this->initialFilename = String_cat(xdgConfigHome, "/htop/htoprc");
configDir = xStrdup(xdgConfigHome);
htopDir = String_cat(xdgConfigHome, "/htop");
} else {
this->initialFilename = String_cat(home, CONFIGDIR "/htop/htoprc");
configDir = String_cat(home, CONFIGDIR);
htopDir = String_cat(home, CONFIGDIR "/htop");
}
(void) mkdir(configDir, 0700);
(void) mkdir(htopDir, 0700);
this->initialFilename = String_cat(htopDir, "/htoprc");
free(htopDir);
free(configDir);

legacyDotfile = String_cat(home, "/.htoprc");
}
Expand Down
Loading