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 <string.h> 00022 #include "abstract_mem.h" 00023 00051 fsal_status_t POSIXFSAL_rcp(fsal_handle_t * filehdl, /* IN */ 00052 fsal_op_context_t * context, /* IN */ 00053 fsal_path_t * p_local_path, /* IN */ 00054 fsal_rcpflag_t transfer_opt /* IN */ 00055 ) 00056 { 00057 posixfsal_handle_t * filehandle = (posixfsal_handle_t *) filehdl; 00058 posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; 00059 int local_fd; 00060 int local_flags; 00061 int errsv; 00062 00063 posixfsal_file_t fs_fd; 00064 fsal_openflags_t fs_flags; 00065 00066 fsal_status_t st = FSAL_STATUS_NO_ERROR; 00067 00068 /* default buffer size for RCP: 10MB */ 00069 #define RCP_BUFFER_SIZE 10485760 00070 caddr_t IObuffer; 00071 00072 int to_local = FALSE; 00073 int to_fs = FALSE; 00074 00075 int eof = FALSE; 00076 00077 ssize_t local_size; 00078 fsal_size_t fs_size; 00079 00080 /* sanity checks. */ 00081 00082 if(!filehandle || !p_context || !p_local_path) 00083 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp); 00084 00085 to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL); 00086 to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS); 00087 00088 if(isFullDebug(COMPONENT_FSAL)) 00089 { 00090 if(to_local) 00091 LogFullDebug(COMPONENT_FSAL, 00092 "FSAL_rcp: FSAL -> local file (%s)", p_local_path->path); 00093 00094 if(to_fs) 00095 LogFullDebug(COMPONENT_FSAL, 00096 "FSAL_rcp: local file -> FSAL (%s)", p_local_path->path); 00097 } 00098 00099 /* must give the sens of transfert (exactly one) */ 00100 00101 if((!to_local && !to_fs) || (to_local && to_fs)) 00102 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00103 00104 /* first, open local file with the correct flags */ 00105 00106 if(to_fs) 00107 { 00108 local_flags = O_RDONLY; 00109 } 00110 else 00111 { 00112 local_flags = O_WRONLY | O_TRUNC; 00113 00114 if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00115 local_flags |= O_CREAT; 00116 00117 if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL) 00118 local_flags |= O_EXCL; 00119 00120 } 00121 00122 if(isFullDebug(COMPONENT_FSAL)) 00123 { 00124 char msg[1024]; 00125 00126 msg[0] = '\0'; 00127 00128 if((local_flags & O_RDONLY) == O_RDONLY) 00129 strcat(msg, "O_RDONLY "); 00130 00131 if((local_flags & O_WRONLY) == O_WRONLY) 00132 strcat(msg, "O_WRONLY "); 00133 00134 if((local_flags & O_TRUNC) == O_TRUNC) 00135 strcat(msg, "O_TRUNC "); 00136 00137 if((local_flags & O_CREAT) == O_CREAT) 00138 strcat(msg, "O_CREAT "); 00139 00140 if((local_flags & O_EXCL) == O_EXCL) 00141 strcat(msg, "O_EXCL "); 00142 00143 LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s", 00144 p_local_path->path, msg); 00145 } 00146 00147 local_fd = open(p_local_path->path, local_flags); 00148 errsv = errno; 00149 00150 if(local_fd == -1) 00151 { 00152 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rcp); 00153 } 00154 00155 /* call FSAL_open with the correct flags */ 00156 00157 if(to_fs) 00158 { 00159 fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC; 00160 00161 /* invalid flags for local to filesystem */ 00162 00163 if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00164 || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)) 00165 { 00166 /* clean & return */ 00167 close(local_fd); 00168 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00169 } 00170 } 00171 else 00172 { 00173 fs_flags = FSAL_O_RDONLY; 00174 } 00175 00176 if(isFullDebug(COMPONENT_FSAL)) 00177 { 00178 char msg[1024]; 00179 00180 msg[0] = '\0'; 00181 00182 if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY) 00183 strcat(msg, "FSAL_O_RDONLY "); 00184 00185 if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY) 00186 strcat(msg, "FSAL_O_WRONLY "); 00187 00188 if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC) 00189 strcat(msg, "FSAL_O_TRUNC "); 00190 00191 LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg); 00192 } 00193 00194 st = POSIXFSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL); 00195 00196 if(FSAL_IS_ERROR(st)) 00197 { 00198 /* clean & return */ 00199 close(local_fd); 00200 Return(st.major, st.minor, INDEX_FSAL_rcp); 00201 } 00202 LogFullDebug(COMPONENT_FSAL, "Allocating IO buffer of size %llu", 00203 (unsigned long long)RCP_BUFFER_SIZE); 00204 00205 /* Allocates buffer */ 00206 00207 IObuffer = gsh_malloc(RCP_BUFFER_SIZE); 00208 00209 if(IObuffer == NULL) 00210 { 00211 /* clean & return */ 00212 close(local_fd); 00213 POSIXFSAL_close(&fs_fd); 00214 Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp); 00215 } 00216 00217 /* read/write loop */ 00218 00219 while(!eof) 00220 { 00221 /* initialize error code */ 00222 st = FSAL_STATUS_NO_ERROR; 00223 00224 LogFullDebug(COMPONENT_FSAL, "Read a block from source"); 00225 00226 /* read */ 00227 00228 if(to_fs) /* from local filesystem */ 00229 { 00230 local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE); 00231 00232 if(local_size == -1) 00233 { 00234 st.major = ERR_FSAL_IO; 00235 st.minor = errno; 00236 break; /* exit loop */ 00237 } 00238 00239 eof = (local_size == 0); 00240 00241 } 00242 else /* from FSAL filesystem */ 00243 { 00244 fs_size = 0; 00245 st = POSIXFSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof); 00246 00247 if(FSAL_IS_ERROR(st)) 00248 break; /* exit loop */ 00249 00250 LogFullDebug(COMPONENT_FSAL, "Size read from source: %llu", 00251 (unsigned long long)fs_size); 00252 } 00253 00254 /* write (if not eof) */ 00255 00256 if(!eof || ((!to_fs) && (fs_size > 0))) 00257 { 00258 00259 LogFullDebug(COMPONENT_FSAL, "Write a block to destination"); 00260 00261 if(to_fs) /* to FSAL filesystem */ 00262 { 00263 00264 st = POSIXFSAL_write(&fs_fd, p_context, NULL, local_size, IObuffer, &fs_size); 00265 00266 if(FSAL_IS_ERROR(st)) 00267 break; /* exit loop */ 00268 00269 } 00270 else /* to local filesystem */ 00271 { 00272 00273 local_size = write(local_fd, IObuffer, fs_size); 00274 00275 LogFullDebug(COMPONENT_FSAL, "Size written to target: %llu", 00276 (unsigned long long)local_size); 00277 00278 if(local_size == -1) 00279 { 00280 st.major = ERR_FSAL_IO; 00281 st.minor = errno; 00282 break; /* exit loop */ 00283 } 00284 00285 } /* if to_fs */ 00286 00287 } /* if eof */ 00288 else 00289 LogFullDebug(COMPONENT_FSAL, "End of source file reached"); 00290 } /* while !eof */ 00291 00292 /* Clean */ 00293 00294 gsh_free(IObuffer); 00295 close(local_fd); 00296 POSIXFSAL_close(&fs_fd); 00297 00298 /* return status. */ 00299 00300 Return(st.major, st.minor, INDEX_FSAL_rcp); 00301 00302 }