nfs-ganesha 1.4
|
00001 /* 00002 * Copyright (C) International Business Machines Corp., 2010 00003 * Author(s): Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 00004 * 00005 * This library is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as published 00007 * by the Free Software Foundation; either version 2.1 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 00013 * the GNU Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #ifndef HANDLE_H 00021 #define HANDLE_H 00022 00023 #include "config.h" 00024 00025 #include <stdio.h> 00026 #include <stdlib.h> 00027 00028 #include <fcntl.h> 00029 #include <unistd.h> 00030 #include <errno.h> 00031 #include <sys/types.h> 00032 #include <sys/stat.h> 00033 #include <string.h> 00034 #include <stddef.h> /* For having offsetof defined */ 00035 00036 00037 #ifdef LINUX 00038 #ifndef MAX_HANDLE_SZ 00039 00040 /* syscalls introduced in 2.6.39 and enabled in glibc 2.14 00041 * if we are not building against 2.14, create our own versions 00042 * as inlines. Glibc versions are externs to glibc... 00043 */ 00044 00045 #define MAX_HANDLE_SZ 128 00046 typedef unsigned int __u32; 00047 00048 struct file_handle { 00049 __u32 handle_bytes; 00050 int handle_type; 00051 /* file identifier */ 00052 unsigned char f_handle[0]; 00053 }; 00054 00055 #if defined(__i386__) 00056 #define __NR_name_to_handle_at 341 00057 #define __NR_open_by_handle_at 342 00058 #elif defined(__x86_64__) 00059 #define __NR_name_to_handle_at 303 00060 #define __NR_open_by_handle_at 304 00061 #endif 00062 00063 static inline int name_to_handle_at(int mdirfd, const char *name, 00064 struct file_handle * handle, int *mnt_id, int flags) 00065 { 00066 return syscall(__NR_name_to_handle_at, mdirfd, name, handle, mnt_id, flags); 00067 } 00068 00069 static inline int open_by_handle_at(int mdirfd, struct file_handle * handle, 00070 int flags) 00071 { 00072 return syscall(__NR_open_by_handle_at, mdirfd, handle, flags); 00073 } 00074 #endif 00075 00076 #ifndef AT_FDCWD 00077 #error "Very old kernel and/or glibc" 00078 #endif 00079 00080 #ifndef AT_EMPTY_PATH 00081 #define AT_EMPTY_PATH 0x1000 00082 #endif 00083 00084 #ifndef O_PATH 00085 #define O_PATH 010000000 00086 #endif 00087 00088 #ifndef O_NOACCESS 00089 #define O_NOACCESS O_ACCMODE 00090 #endif 00091 00092 #else /* ifdef LINUX */ 00093 #error "Not Linux, no by handle syscalls defined." 00094 #endif 00095 00096 static inline size_t vfs_sizeof_handle(struct file_handle *hdl) 00097 { 00098 return offsetof(struct file_handle, f_handle) + hdl->handle_bytes; 00099 } 00100 00101 /* This is large enough for PanFS file handles embedded in a BSD fhandle */ 00102 #define VFS_HANDLE_LEN 48 00103 typedef struct vfs_file_handle { 00104 unsigned int handle_bytes; 00105 int handle_type; 00106 unsigned char handle[VFS_HANDLE_LEN]; 00107 } vfs_file_handle_t ; 00108 00109 00110 static inline int vfs_name_to_handle(const char *name, vfs_file_handle_t *fh, int *mnt_id) 00111 { 00112 return name_to_handle_at(AT_FDCWD, name, (struct file_handle *)fh, mnt_id, AT_SYMLINK_FOLLOW); 00113 } 00114 00115 static inline int vfs_lname_to_handle(const char *name, vfs_file_handle_t *fh, int *mnt_id ) 00116 { 00117 return name_to_handle_at(AT_FDCWD, name, (struct file_handle *)fh, mnt_id, 0); 00118 } 00119 00120 static inline int vfs_fd_to_handle(int fd, vfs_file_handle_t * fh, int *mnt_id) 00121 { 00122 return name_to_handle_at(fd, "", (struct file_handle *)fh, mnt_id, AT_EMPTY_PATH); 00123 } 00124 00125 static inline int vfs_open_by_handle(int mountfd, vfs_file_handle_t * fh, int flags) 00126 { 00127 return open_by_handle_at(mountfd, (struct file_handle *)fh, flags); 00128 } 00129 00130 static inline int vfs_name_by_handle_at(int atfd, const char *name, vfs_file_handle_t *fh) 00131 { 00132 int mnt_id; 00133 00134 return name_to_handle_at(atfd, name,(struct file_handle *)fh, &mnt_id, 0); 00135 } 00136 00137 static inline ssize_t vfs_readlink_by_handle(int mountfd, vfs_file_handle_t *fh, char *buf, size_t bufsize) 00138 { 00139 int fd, ret; 00140 00141 fd = vfs_open_by_handle(mountfd, fh, (O_PATH|O_NOACCESS)); 00142 if (fd < 0) 00143 return fd; 00144 ret = readlinkat(fd, "", buf, bufsize); 00145 close(fd); 00146 return ret; 00147 } 00148 00149 static inline int vfs_stat_by_handle(int mountfd, vfs_file_handle_t *fh, struct stat *buf) 00150 { 00151 int fd, ret; 00152 fd = vfs_open_by_handle(mountfd, fh, (O_PATH|O_NOACCESS)); 00153 if (fd < 0) 00154 return fd; 00155 ret = fstatat(fd, "", buf, AT_EMPTY_PATH); 00156 close(fd); 00157 return ret; 00158 } 00159 00160 static inline int vfs_link_by_handle(int mountfd, vfs_file_handle_t *fh, int newdirfd, char *newname) 00161 { 00162 int fd, ret; 00163 fd = vfs_open_by_handle(mountfd, fh, (O_PATH|O_NOACCESS)); 00164 if (fd < 0) 00165 return fd; 00166 ret = linkat(fd, "", newdirfd, newname, AT_EMPTY_PATH); 00167 close(fd); 00168 return ret; 00169 } 00170 00171 static inline int vfs_chown_by_handle(int mountfd, vfs_file_handle_t *fh, uid_t owner, gid_t group) 00172 { 00173 int fd, ret; 00174 fd = vfs_open_by_handle(mountfd, fh, (O_PATH|O_NOACCESS)); 00175 if (fd < 0) 00176 return fd; 00177 ret = fchownat(fd, "", owner, group, AT_EMPTY_PATH); 00178 close(fd); 00179 return ret; 00180 } 00181 00182 #endif