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 #include "abstract_mem.h" 00022 00023 #include <sys/types.h> 00024 #include <sys/stat.h> 00025 #include <fcntl.h> 00026 00060 fsal_status_t FSAL_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 fsal_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(isFullDebug(COMPONENT_FSAL)) 00103 { 00104 if(to_local) 00105 LogFullDebug(COMPONENT_FSAL, "FSAL_rcp: FSAL -> local file (%s)", 00106 p_local_path->path); 00107 00108 if(to_fs) 00109 LogFullDebug(COMPONENT_FSAL, "FSAL_rcp: local file -> FSAL (%s)", 00110 p_local_path->path); 00111 } 00112 00113 /* must give the sens of transfert (exactly one) */ 00114 00115 if((!to_local && !to_fs) || (to_local && to_fs)) 00116 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00117 00118 /* first, open local file with the correct flags */ 00119 00120 if(to_fs) 00121 { 00122 local_flags = O_RDONLY; 00123 } 00124 else 00125 { 00126 local_flags = O_WRONLY | O_TRUNC; 00127 00128 if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00129 local_flags |= O_CREAT; 00130 00131 if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL) 00132 local_flags |= O_EXCL; 00133 00134 } 00135 00136 if(isFullDebug(OMPONENT_FSAL)) 00137 { 00138 00139 char msg[1024]; 00140 00141 msg[0] = '\0'; 00142 00143 if((local_flags & O_RDONLY) == O_RDONLY) 00144 strcat(msg, "O_RDONLY "); 00145 00146 if((local_flags & O_WRONLY) == O_WRONLY) 00147 strcat(msg, "O_WRONLY "); 00148 00149 if((local_flags & O_TRUNC) == O_TRUNC) 00150 strcat(msg, "O_TRUNC "); 00151 00152 if((local_flags & O_CREAT) == O_CREAT) 00153 strcat(msg, "O_CREAT "); 00154 00155 if((local_flags & O_EXCL) == O_EXCL) 00156 strcat(msg, "O_EXCL "); 00157 00158 LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s", 00159 p_local_path->path, msg); 00160 00161 } 00162 00163 local_fd = open(p_local_path->path, local_flags, 0644); 00164 00165 if(local_fd == -1) 00166 { 00167 /* todo : put a function in fsal_convert.c that convert your local 00168 * filesystem errors to an FSAL error code. 00169 * So you will have a call like : 00170 * Return( unix2fsal_error(errno) , errno , INDEX_FSAL_rcp ); 00171 */ 00172 } 00173 00174 /* call FSAL_open with the correct flags */ 00175 00176 if(to_fs) 00177 { 00178 fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC; 00179 00180 /* invalid flags for local to filesystem */ 00181 00182 if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00183 || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)) 00184 { 00185 /* clean & return */ 00186 close(local_fd); 00187 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00188 } 00189 } 00190 else 00191 { 00192 fs_flags = FSAL_O_RDONLY; 00193 } 00194 00195 if(isFullDebug(COMPONENT_FSAL)) 00196 { 00197 char msg[1024]; 00198 00199 msg[0] = '\0'; 00200 00201 if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY) 00202 strcat(msg, "FSAL_O_RDONLY "); 00203 00204 if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY) 00205 strcat(msg, "FSAL_O_WRONLY "); 00206 00207 if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC) 00208 strcat(msg, "FSAL_O_TRUNC "); 00209 00210 LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg); 00211 } 00212 00213 st = FSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL); 00214 00215 if(FSAL_IS_ERROR(st)) 00216 { 00217 /* clean & return */ 00218 close(local_fd); 00219 Return(st.major, st.minor, INDEX_FSAL_rcp); 00220 } 00221 00222 LogFullDebug(COMPONENT_FSAL, "Allocating IO buffer of size %llu", 00223 (unsigned long long)RCP_BUFFER_SIZE); 00224 00225 /* Allocates buffer */ 00226 00227 IObuffer = gsh_malloc(RCP_BUFFER_SIZE); 00228 00229 if(IObuffer == NULL) 00230 { 00231 /* clean & return */ 00232 close(local_fd); 00233 FSAL_close(&fs_fd); 00234 Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp); 00235 } 00236 00237 /* read/write loop */ 00238 00239 while(!eof) 00240 { 00241 /* initialize error code */ 00242 st = FSAL_STATUS_NO_ERROR; 00243 00244 LogFullDebug(COMPONENT_FSAL, "Read a block from source"); 00245 00246 /* read */ 00247 00248 if(to_fs) /* from local filesystem */ 00249 { 00250 local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE); 00251 00252 if(local_size == -1) 00253 { 00254 st.major = ERR_FSAL_IO; 00255 st.minor = errno; 00256 break; /* exit loop */ 00257 } 00258 00259 eof = (local_size == 0); 00260 00261 } 00262 else /* from FSAL filesystem */ 00263 { 00264 st = FSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof); 00265 00266 if(FSAL_IS_ERROR(st)) 00267 break; /* exit loop */ 00268 00269 } 00270 00271 /* write (if not eof) */ 00272 00273 if(!eof) 00274 { 00275 LogFullDebug(COMPONENT_FSAL, "Write a block to destination"); 00276 00277 if(to_fs) /* to FSAL filesystem */ 00278 { 00279 00280 st = FSAL_write(&fs_fd, pcontext, NULL, local_size, IObuffer, &fs_size); 00281 00282 if(FSAL_IS_ERROR(st)) 00283 break; /* exit loop */ 00284 00285 } 00286 else /* to local filesystem */ 00287 { 00288 00289 local_size = write(local_fd, IObuffer, fs_size); 00290 00291 if(local_size == -1) 00292 { 00293 st.major = ERR_FSAL_IO; 00294 st.minor = errno; 00295 break; /* exit loop */ 00296 } 00297 00298 } /* if to_fs */ 00299 00300 } /* if eof */ 00301 else 00302 LogFullDebug(COMPONENT_FSAL, "End of source file reached"); 00303 } /* while !eof */ 00304 00305 /* Clean */ 00306 00307 gsh_free(IObuffer); 00308 close(local_fd); 00309 FSAL_close(&fs_fd); 00310 00311 /* return status. */ 00312 00313 Return(st.major, st.minor, INDEX_FSAL_rcp); 00314 00315 }