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