nfs-ganesha 1.4

fsal_handle_syscalls.h

Go to the documentation of this file.
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