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 "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 }