nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 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 #include <string.h> 00023 #include <fcntl.h> 00024 00025 char *strcat(char *dest, const char *src); 00026 00054 fsal_status_t XFSFSAL_rcp(fsal_handle_t * filehandle, /* IN */ 00055 fsal_op_context_t * p_context, /* IN */ 00056 fsal_path_t * p_local_path, /* IN */ 00057 fsal_rcpflag_t transfer_opt /* IN */ 00058 ) 00059 { 00060 00061 int local_fd; 00062 int local_flags; 00063 int errsv; 00064 00065 xfsfsal_file_t fs_fd; 00066 fsal_openflags_t fs_flags; 00067 00068 fsal_status_t st = FSAL_STATUS_NO_ERROR; 00069 00070 /* default buffer size for RCP: 10MB */ 00071 #define RCP_BUFFER_SIZE 10485760 00072 caddr_t IObuffer; 00073 00074 int to_local = FALSE; 00075 int to_fs = FALSE; 00076 00077 int eof = FALSE; 00078 00079 ssize_t local_size = 0; 00080 fsal_size_t fs_size; 00081 00082 /* sanity checks. */ 00083 00084 if(!filehandle || !p_context || !p_local_path) 00085 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rcp); 00086 00087 to_local = ((transfer_opt & FSAL_RCP_FS_TO_LOCAL) == FSAL_RCP_FS_TO_LOCAL); 00088 to_fs = ((transfer_opt & FSAL_RCP_LOCAL_TO_FS) == FSAL_RCP_LOCAL_TO_FS); 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 /* must give the sens of transfert (exactly one) */ 00099 00100 if((!to_local && !to_fs) || (to_local && to_fs)) 00101 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00102 00103 /* first, open local file with the correct flags */ 00104 00105 if(to_fs) 00106 { 00107 local_flags = O_RDONLY; 00108 } 00109 else 00110 { 00111 local_flags = O_WRONLY | O_TRUNC; 00112 00113 if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00114 local_flags |= O_CREAT; 00115 00116 if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL) 00117 local_flags |= O_EXCL; 00118 00119 } 00120 00121 if(isFullDebug(COMPONENT_FSAL)) 00122 { 00123 char msg[1024]; 00124 00125 msg[0] = '\0'; 00126 00127 if((local_flags & O_RDONLY) == O_RDONLY) 00128 strcat(msg, "O_RDONLY "); 00129 00130 if((local_flags & O_WRONLY) == O_WRONLY) 00131 strcat(msg, "O_WRONLY "); 00132 00133 if((local_flags & O_TRUNC) == O_TRUNC) 00134 strcat(msg, "O_TRUNC "); 00135 00136 if((local_flags & O_CREAT) == O_CREAT) 00137 strcat(msg, "O_CREAT "); 00138 00139 if((local_flags & O_EXCL) == O_EXCL) 00140 strcat(msg, "O_EXCL "); 00141 00142 LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s", 00143 p_local_path->path, msg); 00144 } 00145 00146 local_fd = open(p_local_path->path, local_flags); 00147 errsv = errno; 00148 00149 if(local_fd == -1) 00150 { 00151 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rcp); 00152 } 00153 00154 /* call FSAL_open with the correct flags */ 00155 00156 if(to_fs) 00157 { 00158 fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC; 00159 00160 /* invalid flags for local to filesystem */ 00161 00162 if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT) 00163 || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)) 00164 { 00165 /* clean & return */ 00166 close(local_fd); 00167 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp); 00168 } 00169 } 00170 else 00171 { 00172 fs_flags = FSAL_O_RDONLY; 00173 } 00174 00175 if(isFullDebug(COMPONENT_FSAL)) 00176 { 00177 char msg[1024]; 00178 00179 msg[0] = '\0'; 00180 00181 if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY) 00182 strcat(msg, "FSAL_O_RDONLY "); 00183 00184 if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY) 00185 strcat(msg, "FSAL_O_WRONLY "); 00186 00187 if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC) 00188 strcat(msg, "FSAL_O_TRUNC "); 00189 00190 LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg); 00191 } 00192 00193 st = XFSFSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL); 00194 00195 if(FSAL_IS_ERROR(st)) 00196 { 00197 /* clean & return */ 00198 close(local_fd); 00199 Return(st.major, st.minor, INDEX_FSAL_rcp); 00200 } 00201 LogFullDebug(COMPONENT_FSAL, 00202 "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 XFSFSAL_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 = XFSFSAL_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 00255 /* write (if not eof) */ 00256 00257 if(!eof || ((!to_fs) && (fs_size > 0))) 00258 { 00259 LogFullDebug(COMPONENT_FSAL, "Write a block to destination"); 00260 00261 if(to_fs) /* to FSAL filesystem */ 00262 { 00263 00264 st = XFSFSAL_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 00291 } /* while !eof */ 00292 00293 /* Clean */ 00294 00295 gsh_free(IObuffer); 00296 close(local_fd); 00297 XFSFSAL_close(&fs_fd); 00298 00299 /* return status. */ 00300 00301 Return(st.major, st.minor, INDEX_FSAL_rcp); 00302 00303 }