nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include "fsal.h" 00019 #include "fsal_internal.h" 00020 #include "fsal_convert.h" 00021 00022 #include <sys/types.h> 00023 #include <sys/stat.h> 00024 #include <fcntl.h> 00025 #include <string.h> 00026 00060 fsal_status_t FUSEFSAL_rcp(fsal_handle_t * filehandle, /* IN */ 00061 fsal_op_context_t * p_context, /* IN */ 00062 fsal_path_t * p_local_path, /* IN */ 00063 fsal_rcpflag_t transfer_opt /* IN */ 00064 ) 00065 { 00066 00067 int local_fd; 00068 int local_flags; 00069 00070 fusefsal_file_t fs_fd; 00071 fsal_openflags_t fs_flags; 00072 00073 fsal_status_t st = FSAL_STATUS_NO_ERROR; 00074 00075 /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 00076 * This is a template implementation of rcp based on FSAL_read and FSAL_write 00077 * function. You may chose keeping it or doing your own implementation 00078 * that is optimal for your filesystems. 00079 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 00080 */ 00081 00082 /* default buffer size for RCP: 1MB */ 00083 #define RCP_BUFFER_SIZE 1048576 00084 caddr_t IObuffer; 00085 00086 int to_local = FALSE; 00087 int to_fs = FALSE; 00088 00089 int eof = FALSE; 00090 00091 ssize_t local_size; 00092 fsal_size_t fs_size; 00093 00094 /* sanity checks. */ 00095 00096 if(!filehandle || !p_context || !p_local_path) 00097 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp); 00098 00099 to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL); 00100 to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS); 00101 00102 if(to_local) 00103 LogFullDebug(COMPONENT_FSAL, "FSAL_rcp: FSAL -> local file (%s)", 00104 p_local_path->path); 00105 00106 if(to_fs) 00107 LogFullDebug(COMPONENT_FSAL, "FSAL_rcp: local file -> FSAL (%s)", 00108 p_local_path->path); 00109 00110 /* must give the sens of transfert (exactly one) */ 00111 00112 if((!to_local && !to_fs) || (to_local && to_fs)) 00113 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00114 00115 /* first, open local file with the correct flags */ 00116 00117 if(to_fs) 00118 { 00119 local_flags = O_RDONLY; 00120 } 00121 else 00122 { 00123 local_flags = O_WRONLY | O_TRUNC; 00124 00125 if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00126 local_flags |= O_CREAT; 00127 00128 if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL) 00129 local_flags |= O_EXCL; 00130 00131 } 00132 00133 if(isFullDebug(COMPONENT_FSAL)) 00134 { 00135 char msg[1024]; 00136 00137 msg[0] = '\0'; 00138 00139 if((local_flags & O_RDONLY) == O_RDONLY) 00140 strcat(msg, "O_RDONLY "); 00141 00142 if((local_flags & O_WRONLY) == O_WRONLY) 00143 strcat(msg, "O_WRONLY "); 00144 00145 if((local_flags & O_TRUNC) == O_TRUNC) 00146 strcat(msg, "O_TRUNC "); 00147 00148 if((local_flags & O_CREAT) == O_CREAT) 00149 strcat(msg, "O_CREAT "); 00150 00151 if((local_flags & O_EXCL) == O_EXCL) 00152 strcat(msg, "O_EXCL "); 00153 00154 LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s", 00155 p_local_path->path, msg); 00156 } 00157 00158 local_fd = open(p_local_path->path, local_flags, 0644); 00159 00160 if(local_fd == -1) 00161 { 00162 /* todo : put a function in fsal_convert.c that convert your local 00163 * filesystem errors to an FSAL error code. 00164 * So you will have a call like : 00165 * Return( unix2fsal_error(errno) , errno , INDEX_FSAL_rcp ); 00166 */ 00167 } 00168 00169 /* call FSAL_open with the correct flags */ 00170 00171 if(to_fs) 00172 { 00173 fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC; 00174 00175 /* invalid flags for local to filesystem */ 00176 00177 if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00178 || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)) 00179 { 00180 /* clean & return */ 00181 close(local_fd); 00182 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00183 } 00184 } 00185 else 00186 { 00187 fs_flags = FSAL_O_RDONLY; 00188 } 00189 00190 if(isFullDebug(COMPONENT_FSAL)) 00191 { 00192 00193 char msg[1024]; 00194 00195 msg[0] = '\0'; 00196 00197 if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY) 00198 strcat(msg, "FSAL_O_RDONLY "); 00199 00200 if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY) 00201 strcat(msg, "FSAL_O_WRONLY "); 00202 00203 if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC) 00204 strcat(msg, "FSAL_O_TRUNC "); 00205 00206 LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg); 00207 00208 } 00209 00210 st = FUSEFSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL); 00211 00212 if(FSAL_IS_ERROR(st)) 00213 { 00214 /* clean & return */ 00215 close(local_fd); 00216 Return(st.major, st.minor, INDEX_FSAL_rcp); 00217 } 00218 00219 LogFullDebug(COMPONENT_FSAL, "Allocating IO buffer of size %llu", 00220 (unsigned long long)RCP_BUFFER_SIZE); 00221 00222 /* Allocates buffer */ 00223 00224 IObuffer = gsh_malloc(RCP_BUFFER_SIZE); 00225 00226 if(IObuffer == NULL) 00227 { 00228 /* clean & return */ 00229 close(local_fd); 00230 FUSEFSAL_close(&fs_fd); 00231 Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp); 00232 } 00233 00234 /* read/write loop */ 00235 00236 while(!eof) 00237 { 00238 /* initialize error code */ 00239 st = FSAL_STATUS_NO_ERROR; 00240 00241 LogFullDebug(COMPONENT_FSAL, "Read a block from source"); 00242 00243 /* read */ 00244 00245 if(to_fs) /* from local filesystem */ 00246 { 00247 local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE); 00248 00249 if(local_size == -1) 00250 { 00251 st.major = ERR_FSAL_IO; 00252 st.minor = errno; 00253 break; /* exit loop */ 00254 } 00255 00256 eof = (local_size == 0); 00257 00258 } 00259 else /* from FSAL filesystem */ 00260 { 00261 st = FUSEFSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof); 00262 00263 if(FSAL_IS_ERROR(st)) 00264 break; /* exit loop */ 00265 00266 } 00267 00268 /* write (if not eof) */ 00269 00270 if(!eof) 00271 { 00272 LogFullDebug(COMPONENT_FSAL, "Write a block to destination"); 00273 00274 if(to_fs) /* to FSAL filesystem */ 00275 { 00276 00277 st = FUSEFSAL_write(&fs_fd, p_context, NULL, local_size, IObuffer, &fs_size); 00278 00279 if(FSAL_IS_ERROR(st)) 00280 break; /* exit loop */ 00281 00282 } 00283 else /* to local filesystem */ 00284 { 00285 00286 local_size = write(local_fd, IObuffer, fs_size); 00287 00288 if(local_size == -1) 00289 { 00290 st.major = ERR_FSAL_IO; 00291 st.minor = errno; 00292 break; /* exit loop */ 00293 } 00294 00295 } /* if to_fs */ 00296 00297 } /* if eof */ 00298 else 00299 LogFullDebug(COMPONENT_FSAL, "End of source file reached"); 00300 00301 } /* while !eof */ 00302 00303 /* Clean */ 00304 00305 gsh_free(IObuffer); 00306 close(local_fd); 00307 FUSEFSAL_close(&fs_fd); 00308 00309 /* return status. */ 00310 00311 Return(st.major, st.minor, INDEX_FSAL_rcp); 00312 00313 }