fchmodat.c raw

   1  #include <sys/stat.h>
   2  #include <fcntl.h>
   3  #include <errno.h>
   4  #include "syscall.h"
   5  #include "kstat.h"
   6  
   7  int fchmodat(int fd, const char *path, mode_t mode, int flag)
   8  {
   9  	if (!flag) return syscall(SYS_fchmodat, fd, path, mode, flag);
  10  
  11  	if (flag != AT_SYMLINK_NOFOLLOW)
  12  		return __syscall_ret(-EINVAL);
  13  
  14  	struct kstat st;
  15  	int ret, fd2;
  16  	char proc[15+3*sizeof(int)];
  17  
  18  	if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag)))
  19  		return __syscall_ret(ret);
  20  	if (S_ISLNK(st.st_mode))
  21  		return __syscall_ret(-EOPNOTSUPP);
  22  
  23  	if ((fd2 = __syscall(SYS_openat, fd, path, O_RDONLY|O_PATH|O_NOFOLLOW|O_NOCTTY|O_CLOEXEC)) < 0) {
  24  		if (fd2 == -ELOOP)
  25  			return __syscall_ret(-EOPNOTSUPP);
  26  		return __syscall_ret(fd2);
  27  	}
  28  
  29  	__procfdname(proc, fd2);
  30  	ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0);
  31  	if (!ret) {
  32  		if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP;
  33  		else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
  34  	}
  35  
  36  	__syscall(SYS_close, fd2);
  37  	return __syscall_ret(ret);
  38  }
  39