nfs-ganesha 1.4

fsal_rcp.c

Go to the documentation of this file.
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 }