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 
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 #include <string.h>
00026 
00060 fsal_status_t FUSEFSAL_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   fusefsal_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(to_local)
00103     LogFullDebug(COMPONENT_FSAL, "FSAL_rcp: FSAL -> local file (%s)",
00104                  p_local_path->path);
00105 
00106   if(to_fs)
00107     LogFullDebug(COMPONENT_FSAL, "FSAL_rcp: local file -> FSAL (%s)",
00108                  p_local_path->path);
00109 
00110   /* must give the sens of transfert (exactly one) */
00111 
00112   if((!to_local && !to_fs) || (to_local && to_fs))
00113     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
00114 
00115   /* first, open local file with the correct flags */
00116 
00117   if(to_fs)
00118     {
00119       local_flags = O_RDONLY;
00120     }
00121   else
00122     {
00123       local_flags = O_WRONLY | O_TRUNC;
00124 
00125       if((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
00126         local_flags |= O_CREAT;
00127 
00128       if((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL)
00129         local_flags |= O_EXCL;
00130 
00131     }
00132 
00133   if(isFullDebug(COMPONENT_FSAL))
00134     {
00135       char msg[1024];
00136 
00137       msg[0] = '\0';
00138 
00139       if((local_flags & O_RDONLY) == O_RDONLY)
00140         strcat(msg, "O_RDONLY ");
00141 
00142       if((local_flags & O_WRONLY) == O_WRONLY)
00143         strcat(msg, "O_WRONLY ");
00144 
00145       if((local_flags & O_TRUNC) == O_TRUNC)
00146         strcat(msg, "O_TRUNC ");
00147 
00148       if((local_flags & O_CREAT) == O_CREAT)
00149         strcat(msg, "O_CREAT ");
00150 
00151       if((local_flags & O_EXCL) == O_EXCL)
00152         strcat(msg, "O_EXCL ");
00153 
00154       LogFullDebug(COMPONENT_FSAL, "Openning local file %s with flags: %s",
00155                    p_local_path->path, msg);
00156     }
00157 
00158   local_fd = open(p_local_path->path, local_flags, 0644);
00159 
00160   if(local_fd == -1)
00161     {
00162       /* todo : put a function in fsal_convert.c that convert your local
00163        * filesystem errors to an FSAL error code.
00164        * So you will have a call like :
00165        * Return( unix2fsal_error(errno) , errno , INDEX_FSAL_rcp );
00166        */
00167     }
00168 
00169   /* call FSAL_open with the correct flags */
00170 
00171   if(to_fs)
00172     {
00173       fs_flags = FSAL_O_WRONLY | FSAL_O_TRUNC;
00174 
00175       /* invalid flags for local to filesystem */
00176 
00177       if(((transfer_opt & FSAL_RCP_LOCAL_CREAT) == FSAL_RCP_LOCAL_CREAT)
00178          || ((transfer_opt & FSAL_RCP_LOCAL_EXCL) == FSAL_RCP_LOCAL_EXCL))
00179         {
00180           /* clean & return */
00181           close(local_fd);
00182           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rcp);
00183         }
00184     }
00185   else
00186     {
00187       fs_flags = FSAL_O_RDONLY;
00188     }
00189 
00190   if(isFullDebug(COMPONENT_FSAL))
00191     {
00192 
00193       char msg[1024];
00194 
00195       msg[0] = '\0';
00196 
00197       if((fs_flags & FSAL_O_RDONLY) == FSAL_O_RDONLY)
00198         strcat(msg, "FSAL_O_RDONLY ");
00199 
00200       if((fs_flags & FSAL_O_WRONLY) == FSAL_O_WRONLY)
00201         strcat(msg, "FSAL_O_WRONLY ");
00202 
00203       if((fs_flags & FSAL_O_TRUNC) == FSAL_O_TRUNC)
00204         strcat(msg, "FSAL_O_TRUNC ");
00205 
00206       LogFullDebug(COMPONENT_FSAL, "Openning FSAL file with flags: %s", msg);
00207 
00208     }
00209 
00210   st = FUSEFSAL_open(filehandle, p_context, fs_flags, &fs_fd, NULL);
00211 
00212   if(FSAL_IS_ERROR(st))
00213     {
00214       /* clean & return */
00215       close(local_fd);
00216       Return(st.major, st.minor, INDEX_FSAL_rcp);
00217     }
00218 
00219   LogFullDebug(COMPONENT_FSAL,  "Allocating IO buffer of size %llu",
00220                (unsigned long long)RCP_BUFFER_SIZE);
00221 
00222   /* Allocates buffer */
00223 
00224   IObuffer = gsh_malloc(RCP_BUFFER_SIZE);
00225 
00226   if(IObuffer == NULL)
00227     {
00228       /* clean & return */
00229       close(local_fd);
00230       FUSEFSAL_close(&fs_fd);
00231       Return(ERR_FSAL_NOMEM, ENOMEM, INDEX_FSAL_rcp);
00232     }
00233 
00234   /* read/write loop */
00235 
00236   while(!eof)
00237     {
00238       /* initialize error code */
00239       st = FSAL_STATUS_NO_ERROR;
00240 
00241       LogFullDebug(COMPONENT_FSAL, "Read a block from source");
00242 
00243       /* read */
00244 
00245       if(to_fs)                 /* from local filesystem */
00246         {
00247           local_size = read(local_fd, IObuffer, RCP_BUFFER_SIZE);
00248 
00249           if(local_size == -1)
00250             {
00251               st.major = ERR_FSAL_IO;
00252               st.minor = errno;
00253               break;            /* exit loop */
00254             }
00255 
00256           eof = (local_size == 0);
00257 
00258         }
00259       else                      /* from FSAL filesystem */
00260         {
00261           st = FUSEFSAL_read(&fs_fd, NULL, RCP_BUFFER_SIZE, IObuffer, &fs_size, &eof);
00262 
00263           if(FSAL_IS_ERROR(st))
00264             break;              /* exit loop */
00265 
00266         }
00267 
00268       /* write (if not eof) */
00269 
00270       if(!eof)
00271         {
00272           LogFullDebug(COMPONENT_FSAL, "Write a block to destination");
00273 
00274           if(to_fs)             /* to FSAL filesystem */
00275             {
00276 
00277               st = FUSEFSAL_write(&fs_fd, p_context, NULL, local_size, IObuffer, &fs_size);
00278 
00279               if(FSAL_IS_ERROR(st))
00280                 break;          /* exit loop */
00281 
00282             }
00283           else                  /* to local filesystem */
00284             {
00285 
00286               local_size = write(local_fd, IObuffer, fs_size);
00287 
00288               if(local_size == -1)
00289                 {
00290                   st.major = ERR_FSAL_IO;
00291                   st.minor = errno;
00292                   break;        /* exit loop */
00293                 }
00294 
00295             }                   /* if to_fs */
00296 
00297         }                       /* if eof */
00298       else
00299         LogFullDebug(COMPONENT_FSAL, "End of source file reached");
00300 
00301     }                           /* while !eof */
00302 
00303   /* Clean */
00304 
00305   gsh_free(IObuffer);
00306   close(local_fd);
00307   FUSEFSAL_close(&fs_fd);
00308 
00309   /* return status. */
00310 
00311   Return(st.major, st.minor, INDEX_FSAL_rcp);
00312 
00313 }