forked from public/pyceo
parent
a51cbe4e55
commit
a834ffda8f
@ -1,4 +1,5 @@ |
||||
*.o |
||||
/addmember |
||||
/addclub |
||||
/zfsaddhomedir |
||||
/config-test |
||||
|
@ -1,4 +1,3 @@ |
||||
#include <sys/types.h> |
||||
|
||||
int ceo_create_home(char *, uid_t, gid_t, acl_t, acl_t); |
||||
int ceo_set_quota(char *, int); |
||||
int ceo_create_home(char *, uid_t, gid_t, char *, char *); |
||||
|
@ -0,0 +1,140 @@ |
||||
#include <stdio.h> |
||||
#include <unistd.h> |
||||
#include <dirent.h> |
||||
#include <limits.h> |
||||
#include <sys/stat.h> |
||||
#include <sys/types.h> |
||||
#include <fcntl.h> |
||||
#include <assert.h> |
||||
#include "util.h" |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
if(argc < 6) { |
||||
fprintf(stderr, "Usage: zfsaddhomedir homedir skeldir uid gid mode acl\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// TODO: check return of spawnv
|
||||
{ |
||||
char *homedir = argv[1]; |
||||
char *skeldir = argv[2]; |
||||
char *mode = argv[5]; |
||||
char *acl = (argc >= 7) ? argv[6] : NULL; |
||||
uid_t uid, gid; |
||||
char *zfs_bin = "/usr/sbin/zfs"; |
||||
char *chmod_bin = "/usr/bin/chmod"; |
||||
char *dataset = homedir + 1; |
||||
char *create_argv[] = { "zfs", "create", dataset, NULL }; |
||||
char *quota_argv[] = { "zfs", "set", "quota=3G", dataset, NULL }; |
||||
char *mode_argv[] = { "chmod", mode, homedir, NULL }; |
||||
char *acl_argv[] = { "chmod", acl, homedir, NULL }; |
||||
DIR *skel; |
||||
struct dirent *skelent; |
||||
|
||||
assert(homedir[0]); |
||||
uid = atol(argv[3]); |
||||
gid = atol(argv[4]); |
||||
|
||||
if(spawnv(zfs_bin, create_argv)) |
||||
return 1; |
||||
if(spawnv(zfs_bin, quota_argv)) |
||||
return 1; |
||||
if(spawnv(chmod_bin, mode_argv)) |
||||
return 1; |
||||
if(acl && spawnv(chmod_bin, acl_argv)) |
||||
return 1; |
||||
|
||||
skel = opendir(skeldir); |
||||
if (!skel) { |
||||
errorpe("failed to open %s", skeldir); |
||||
return -1; |
||||
} |
||||
|
||||
while ((skelent = readdir(skel))) { |
||||
struct stat sb; |
||||
char src[PATH_MAX], dest[PATH_MAX]; |
||||
|
||||
if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, "..")) |
||||
continue; |
||||
|
||||
snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name); |
||||
snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name); |
||||
lstat(src, &sb); |
||||
|
||||
if (sb.st_uid || sb.st_gid) { |
||||
warn("not creating %s due to ownership", dest); |
||||
continue; |
||||
} |
||||
|
||||
if (S_ISREG(sb.st_mode)) { |
||||
int bytes; |
||||
char buf[4096]; |
||||
|
||||
int srcfd = open(src, O_RDONLY); |
||||
if (srcfd == -1) { |
||||
warnpe("open: %s", src); |
||||
continue; |
||||
} |
||||
|
||||
int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777); |
||||
if (destfd == -1) { |
||||
warnpe("open: %s", dest); |
||||
close(srcfd); |
||||
continue; |
||||
} |
||||
|
||||
for (;;) { |
||||
bytes = read(srcfd, buf, sizeof(buf)); |
||||
if (!bytes) |
||||
break; |
||||
if (bytes < 0) { |
||||
warnpe("read"); |
||||
break; |
||||
} |
||||
if (write(destfd, buf, bytes) < 0) { |
||||
warnpe("write"); |
||||
break; |
||||
} |
||||
} |
||||
if (fchown(destfd, uid, gid)) |
||||
errorpe("chown: %s", dest); |
||||
|
||||
close(srcfd); |
||||
close(destfd); |
||||
} else if (S_ISDIR(sb.st_mode)) { |
||||
if (mkdir(dest, sb.st_mode & 0777)) { |
||||
warnpe("mkdir: %s", dest); |
||||
continue; |
||||
} |
||||
if (chown(dest, uid, gid)) |
||||
errorpe("chown: %s", dest); |
||||
} else if (S_ISLNK(sb.st_mode)) { |
||||
char lnkdest[PATH_MAX]; |
||||
int bytes; |
||||
bytes = readlink(src, lnkdest, sizeof(lnkdest)); |
||||
lnkdest[bytes] = '\0'; |
||||
if (bytes == -1) { |
||||
warnpe("readlink: %s", src); |
||||
continue; |
||||
} |
||||
if (symlink(lnkdest, dest)) { |
||||
warnpe("symlink: %s", dest); |
||||
continue; |
||||
} |
||||
if (lchown(dest, uid, gid)) |
||||
errorpe("lchown: %s", dest); |
||||
} else { |
||||
warn("not creating %s", dest); |
||||
} |
||||
} |
||||
|
||||
closedir(skel); |
||||
|
||||
if (chown(homedir, uid, gid)) { |
||||
errorpe("failed to chown %s", homedir); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue