in src/cache_refresh/cache_refresh.cc [121:209]
int refreshgroupcache() {
syslog(LOG_INFO, "Refreshing group entry cache");
int error_code = 0;
// Temporary buffer to hold passwd entries before writing.
char buffer[kPasswdBufferSize];
NssCache nss_cache(kNssGroupCacheSize);
std::ofstream cache_file(kDefaultBackupGroupPath);
if (cache_file.fail()) {
syslog(LOG_ERR, "Failed to open file %s.", kDefaultBackupGroupPath);
return -1;
}
cache_file << std::unitbuf; // enable automatic flushing
cache_file.exceptions( cache_file.exceptions() | std::ofstream::failbit | std::ofstream::badbit );
chown(kDefaultBackupGroupPath, 0, 0);
chmod(kDefaultBackupGroupPath, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
struct group grp;
nss_cache.Reset();
std::vector<string> users;
while (!nss_cache.OnLastPage() || nss_cache.HasNextEntry()) {
BufferManager buffer_manager(buffer, kPasswdBufferSize);
if (!nss_cache.NssGetgrentHelper(&buffer_manager, &grp, &error_code)) {
if (error_code == ERANGE) {
syslog(LOG_ERR, "Group entry size out of range, skipping");
} else if (error_code == EINVAL) {
syslog(LOG_ERR, "Malformed group entry, skipping");
} else if (error_code == ENOENT) {
syslog(LOG_ERR, "Failure getting groups, quitting");
break;
} else if (error_code == ENOMSG) {
// ENOMSG means OS Login is not enabled.
break;
}
continue;
}
std::string name(grp.gr_name);
users.clear();
if (!GetUsersForGroup(name, &users, &error_code)) {
syslog(LOG_ERR,
"Error getting users for group %s (error_code %d), skipping.",
grp.gr_name, error_code);
continue;
}
try {
cache_file << grp.gr_name << ":" << grp.gr_passwd << ":" << grp.gr_gid << ":";
for (int i = 0; i < (int)users.size(); i++) {
if (i > 0) {
cache_file << ",";
}
cache_file << users[i];
}
cache_file << "\n";
}
catch (const std::ofstream::failure &e) {
syslog(LOG_ERR, "Exception writing file");
error_code = ENOENT;
break;
}
}
try {
cache_file.close();
}
catch (const std::ofstream::failure &e) {
syslog(LOG_ERR, "Exception closing file");
error_code = ENOENT;
}
if (error_code == ENOMSG) {
remove(kDefaultBackupGroupPath);
return 0;
} else if (error_code == ENOENT) {
syslog(LOG_ERR, "Failed to get groups, not updating group cache file, removing %s.", kDefaultBackupGroupPath);
// If the cache file already exists, we don't want to overwrite it on a
// server error. So remove the backup file and return here.
struct stat buffer;
if (stat(kDefaultGroupPath, &buffer) == 0) {
remove(kDefaultBackupGroupPath);
return 0;
}
}
if (rename(kDefaultBackupGroupPath, kDefaultGroupPath) != 0) {
syslog(LOG_ERR, "Error moving %s to %s.", kDefaultBackupGroupPath, kDefaultGroupPath);
remove(kDefaultBackupGroupPath);
}
return 0;
}