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 #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 */