Hi there,
I though it might be a fun excersise to write a little C program which will report all directories, threir owner, group and modes from a given start-point. It would then be really easy to do a Perl/Python/whatever script that takes the output from a "healthy" machine and restores the permissions on another machine.
I've included the C source below. You can compile it with:
cc -o list_dir_modes list_dir_modes.c
and then call the resulting program with
./list_dir_modes
you can optionally provide a starting directory as the first and only parameter.
------ BEGIN CODE:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinfo/ni.h>
#include <dirent.h>
ni_id getId (void *niHandle, const char *name)
{
ni_id rootId;
ni_id tmpId;
ni_entrylist tmpDirs;
ni_entry *entries;
ni_namelist names;
int count;
ni_root(niHandle, &rootId);
ni_list(niHandle, &rootId, "name", &tmpDirs);
entries = tmpDirs.ni_entrylist_val;
for (count = 0; count < tmpDirs.ni_entrylist_len; count++) {
names = *(entries[count].names);
if (names.ni_namelist_len > 0) {
if (strcmp(name, names.ni_namelist_val[0]) == 0) {
tmpId.nii_object = entries[count].id;
tmpId.nii_instance = NULL;
break;
}
}
}
return tmpId;
}
ni_id getUsersId (void *niHandle)
{
return getId(niHandle, "users");
}
ni_id getGroupsId (void *niHandle)
{
return getId(niHandle, "groups");
}
const char* readById (int id, int type)
{
/* Variables */
void *niHandle;
ni_status niReturnCode;
ni_idlist idList;
char idVal[10];
ni_id rootId;
ni_id tmpId;
ni_id tmpPoint;
int count;
ni_namelist names;
char *retVal;
retVal = "Invalid ID";
niReturnCode = ni_open(NULL, "/", &niHandle);
if (niHandle != NULL) {
ni_root(niHandle, &rootId);
if (type == 0) {
tmpId = getUsersId(niHandle);
} else if (type == 1) {
tmpId = getGroupsId(niHandle);
}
sprintf(idVal, "%d", id);
if (type == 0) {
ni_lookup(niHandle, &tmpId, "uid", idVal, &idList);
} else if (type == 1) {
ni_lookup(niHandle, &tmpId, "gid", idVal, &idList);
}
tmpPoint.nii_object = idList.ni_idlist_val[0];
tmpPoint.nii_instance = NULL;
ni_lookupprop(niHandle, &tmpPoint, "name", &names);
retVal = names.ni_namelist_val[0];
ni_free(niHandle);
} else {
printf("Error opening NI.\n");
printf("%s\n", ni_error(niReturnCode));
}
return retVal;
}
const char *readUser (uid_t uid)
{
return readById((int) uid, 0);
}
const char *readGroup (gid_t gid)
{
return readById((int) gid, 1);
}
void reportStats (const char* fileName)
{
/* Variables */
struct stat myStat;
int retCode;
int userMode = 0;
int groupMode = 0;
int otherMode = 0;
const char *userName;
const char *groupName;
uid_t uid;
gid_t gid;
/* Get stats */
stat(fileName, &myStat);
/* Report stats */
uid = myStat.st_uid;
gid = myStat.st_gid;
userName = readUser(uid);
groupName = readGroup(gid);
if ((myStat.st_mode & S_IRUSR) == S_IRUSR) {
userMode += 1;
}
if ((myStat.st_mode & S_IWUSR) == S_IWUSR) {
userMode += 2;
}
if ((myStat.st_mode & S_IXUSR) == S_IXUSR) {
userMode += 4;
}
if ((myStat.st_mode & S_IRGRP) == S_IRGRP) {
groupMode += 1;
}
if ((myStat.st_mode & S_IWGRP) == S_IWGRP) {
groupMode += 2;
}
if ((myStat.st_mode & S_IXGRP) == S_IXGRP) {
groupMode += 4;
}
if ((myStat.st_mode & S_IROTH) == S_IROTH) {
otherMode += 1;
}
if ((myStat.st_mode & S_IWOTH) == S_IWOTH) {
otherMode += 2;
}
if ((myStat.st_mode & S_IXOTH) == S_IXOTH) {
otherMode += 4;
}
printf("%s %s %s %d%d%d\n", fileName, userName, groupName, userMode,
groupMode, otherMode);
}
void scanDirectory (const char* dirName)
{
DIR *dirPointer;
struct dirent *dirEntry;
char *fullName;
dirPointer = opendir(dirName);
while ((dirEntry = readdir(dirPointer)) != NULL) {
if (strcmp(dirEntry->d_name, ".") != 0 &&
strcmp(dirEntry->d_name, "..") != 0 &&
dirEntry->d_type == DT_DIR) {
fullName = malloc(sizeof(char) * (strlen(dirName) +
strlen(dirEntry->d_name) + 1));
strcpy(fullName, dirName);
if (fullName[strlen(fullName) -1] != '/') {
strcat(fullName, "/");
}
strcat(fullName, dirEntry->d_name);
reportStats(fullName);
scanDirectory(fullName);
free(fullName);
}
}
closedir(dirPointer);
}
int main (int argc, const char **argv)
{
int count;
char *startdir;
if (argc > 1) {
startdir = (char*) argv[1];
} else {
startdir = "/";
}
scanDirectory(startdir);
return 0;
}
------ END CODE
C
PS: Sorry this has been a while coming, but I've been busy doing paid work and its been ages since I've programmed C
)))
PPS: This program uses NI to get the user name and group name, so it can't be compiled for other *nix systems without some minor changes ....