nfs-ganesha 1.4

fsal_fileop.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  */
00004 
00013 #ifdef HAVE_CONFIG_H
00014 #include "config.h"
00015 #endif
00016 
00017 #include "fsal.h"
00018 #include "fsal_internal.h"
00019 #include "fsal_convert.h"
00020 
00060 fsal_status_t POSIXFSAL_open_by_name(fsal_handle_t * dirhandle,    /* IN */
00061                                      fsal_name_t * filename,    /* IN */
00062                                      fsal_op_context_t * p_context,        /* IN */
00063                                      fsal_openflags_t openflags,        /* IN */
00064                                      fsal_file_t * file_descriptor,        /* OUT */
00065                                      fsal_attrib_list_t *
00066                                      file_attributes /* [ IN/OUT ] */ )
00067 {
00068   fsal_status_t fsal_status;
00069   posixfsal_handle_t filehandle;
00070 
00071   if(!dirhandle || !filename || !p_context || !file_descriptor)
00072     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open_by_name);
00073 
00074   fsal_status =
00075       POSIXFSAL_lookup(dirhandle, filename, p_context,
00076                        (fsal_handle_t *)&filehandle, file_attributes);
00077   if(FSAL_IS_ERROR(fsal_status))
00078     return fsal_status;
00079 
00080   return POSIXFSAL_open((fsal_handle_t *)&filehandle, p_context,
00081                         openflags, file_descriptor,
00082                         file_attributes);
00083 }
00084 
00115 fsal_status_t POSIXFSAL_open(fsal_handle_t * filehandle, /* IN */
00116                              fsal_op_context_t * context,        /* IN */
00117                              fsal_openflags_t openflags,        /* IN */
00118                              fsal_file_t * file_descriptor,      /* OUT */
00119                              fsal_attrib_list_t * p_file_attributes     /* [ IN/OUT ] */
00120     )
00121 {
00122   posixfsal_handle_t * p_filehandle = (posixfsal_handle_t *) filehandle;
00123   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00124   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00125   int rc, errsv;
00126   fsal_status_t status;
00127 
00128   fsal_path_t fsalpath;
00129   struct stat buffstat;
00130 #ifdef _FSAL_POSIX_USE_STREAM
00131   char posix_flags[4];          /* stores r, r+, w, w+, a, or a+ */
00132 #else
00133   int posix_flags;
00134 #endif
00135 
00136   /* sanity checks.
00137    * note : file_attributes is optional.
00138    */
00139   if(!p_filehandle || !p_context || !p_file_descriptor)
00140     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open);
00141 
00142   status =
00143       fsal_internal_getPathFromHandle(p_context, p_filehandle, 0, &fsalpath, &buffstat);
00144   if(FSAL_IS_ERROR(status))
00145     Return(status.major, status.minor, INDEX_FSAL_open);
00146 
00147   status =
00148       fsal_internal_testAccess(p_context,
00149                                (openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK) |
00150                                FSAL_OWNER_OK, &buffstat, NULL);
00151   if(FSAL_IS_ERROR(status))
00152     Return(status.major, status.minor, INDEX_FSAL_open);
00153 
00154   /* convert fsal open flags to posix open flags */
00155   rc = fsal2posix_openflags(openflags, &posix_flags);
00156 
00157   /* flags conflicts. */
00158   if(rc)
00159     {
00160       LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags);
00161       Return(rc, 0, INDEX_FSAL_open);
00162     }
00163 
00164   TakeTokenFSCall();
00165 #ifdef _FSAL_POSIX_USE_STREAM
00166   p_file_descriptor->p_file = fopen(fsalpath.path, posix_flags);
00167   errsv = errno;
00168   ReleaseTokenFSCall();
00169 
00170   if(!(p_file_descriptor->p_file))
00171     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open);
00172 #else
00173   p_file_descriptor->filefd = open(fsalpath.path, posix_flags);
00174   errsv = errno;
00175   ReleaseTokenFSCall();
00176 #endif
00177 
00178   /* set the read-only flag of the file descriptor */
00179   p_file_descriptor->ro = openflags & FSAL_O_RDONLY;
00180 
00181   /* output attributes */
00182   if(p_file_attributes)
00183     {
00184 
00185       status = posix2fsal_attributes(&buffstat, p_file_attributes);
00186 
00187       if(FSAL_IS_ERROR(status))
00188         {
00189           FSAL_CLEAR_MASK(p_file_attributes->asked_attributes);
00190           FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00191         }
00192     }
00193 
00194   Return(ERR_FSAL_NO_ERROR, errsv, INDEX_FSAL_open); /* use the error... */
00195 
00196 }
00197 
00222 #ifdef _FSAL_POSIX_USE_STREAM
00223 fsal_status_t POSIXFSAL_read(fsal_file_t * file_descriptor,      /* IN */
00224                              fsal_seek_t * p_seek_descriptor,   /* [IN] */
00225                              fsal_size_t buffer_size,   /* IN */
00226                              caddr_t buffer,    /* OUT */
00227                              fsal_size_t * p_read_amount,       /* OUT */
00228                              fsal_boolean_t * p_end_of_file     /* OUT */
00229     )
00230 {
00231   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00232   size_t i_size;
00233   size_t nb_read;
00234   int rc, errsv;
00235 
00236   /* sanity checks. */
00237 
00238   if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
00239     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00240 
00242   i_size = (size_t) buffer_size;
00243 
00244   /* positioning */
00245 
00246   if(p_seek_descriptor)
00247     {
00248 
00249       switch (p_seek_descriptor->whence)
00250         {
00251         case FSAL_SEEK_CUR:
00252           /* set position plus offset */
00253 
00254           TakeTokenFSCall();
00255           rc = fseek(p_file_descriptor->p_file, p_seek_descriptor->offset, SEEK_CUR);
00256           errsv = errno;
00257           ReleaseTokenFSCall();
00258           break;
00259 
00260         case FSAL_SEEK_SET:
00261           /* set absolute position to offset */
00262 
00263           TakeTokenFSCall();
00264           rc = fseek(p_file_descriptor->p_file, p_seek_descriptor->offset, SEEK_SET);
00265           errsv = errno;
00266           ReleaseTokenFSCall();
00267 
00268           break;
00269 
00270         case FSAL_SEEK_END:
00271           /* set end of file plus offset */
00272 
00273           TakeTokenFSCall();
00274           rc = fseek(p_file_descriptor->p_file, p_seek_descriptor->offset, SEEK_END);
00275           errsv = errno;
00276           ReleaseTokenFSCall();
00277 
00278           break;
00279         }
00280 
00281       if(rc)
00282         {
00283 
00284           LogEvent(COMPONENT_FSAL,
00285                    "Error in posix fseek operation (whence=%s, offset=%lld)",
00286                    (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00287                     (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00288                      (p_seek_descriptor->whence ==
00289                       FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00290                    p_seek_descriptor->offset);
00291 
00292           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00293         }
00294 
00295     }
00296 
00297   /* read operation */
00298 
00299   TakeTokenFSCall();
00300 
00301   nb_read = fread(buffer, 1, i_size, p_file_descriptor->p_file);
00302 
00303   ReleaseTokenFSCall();
00304 
00307   if(feof(p_file_descriptor->p_file))
00308     *p_end_of_file = 1;
00309 
00310   if(nb_read == 0 && ferror(p_file_descriptor->p_file))
00311     {
00312       Return(posix2fsal_error(EBADF), EBADF, INDEX_FSAL_read);
00313     }
00314 
00315   *p_read_amount = nb_read;
00316 
00317   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00318 
00319 }
00320 #else
00321 fsal_status_t POSIXFSAL_read(fsal_file_t * file_descriptor,      /* IN */
00322                              fsal_seek_t * p_seek_descriptor,   /* [IN] */
00323                              fsal_size_t buffer_size,   /* IN */
00324                              caddr_t buffer,    /* OUT */
00325                              fsal_size_t * p_read_amount,       /* OUT */
00326                              fsal_boolean_t * p_end_of_file     /* OUT */
00327     )
00328 {
00329 
00330   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00331   size_t i_size;
00332   size_t nb_read;
00333   int rc, errsv;
00334   char c;
00335 
00336   /* sanity checks. */
00337   if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
00338     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00339 
00341   i_size = (size_t) buffer_size;
00342 
00343   /* positioning */
00344 
00345   if(p_seek_descriptor)
00346     {
00347 
00348       switch (p_seek_descriptor->whence)
00349         {
00350         case FSAL_SEEK_CUR:
00351         case FSAL_SEEK_END:
00352           /* set position plus offset */
00353 
00354           TakeTokenFSCall();
00355           rc = lseek(p_file_descriptor->filefd, p_seek_descriptor->offset,
00356                      p_seek_descriptor->whence);
00357           errsv = errno;
00358 
00359           if(rc)
00360             {
00361               LogEvent(COMPONENT_FSAL,
00362                        "Error in posix fseek operation (whence=%s, offset=%"PRId64")",
00363                        (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00364                         (p_seek_descriptor->whence ==
00365                          FSAL_SEEK_SET ? "SEEK_SET" : (p_seek_descriptor->whence
00366                                                        ==
00367                                                        FSAL_SEEK_END ? "SEEK_END"
00368                                                        : "ERROR"))),
00369                        p_seek_descriptor->offset);
00370 
00371               ReleaseTokenFSCall();
00372 
00373               Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
00374             }
00375 
00376           nb_read = read(p_file_descriptor->filefd, buffer, i_size);
00377 
00378           ReleaseTokenFSCall();
00379           break;
00380 
00381         case FSAL_SEEK_SET:
00382           /* set absolute position to offset */
00383 
00384           TakeTokenFSCall();
00385           nb_read =
00386               pread(p_file_descriptor->filefd, buffer, i_size, p_seek_descriptor->offset);
00387           errsv = errno;
00388 
00389           rc = pread(p_file_descriptor->filefd, &c, 1,
00390                      p_seek_descriptor->offset + i_size);
00391           if(rc == 0)
00392             *p_end_of_file = 1;
00393 
00394           ReleaseTokenFSCall();
00395 
00396           break;
00397         }
00398     }
00399   else
00400     {
00401       TakeTokenFSCall();
00402 
00403       nb_read = read(p_file_descriptor->filefd, buffer, i_size);
00404 
00405       ReleaseTokenFSCall();
00406     }
00407 
00409   if(nb_read == -1)
00410     Return(posix2fsal_error(EBADF), EBADF, INDEX_FSAL_read);
00411 
00412   if(nb_read == 0 && i_size != 0)
00413     *p_end_of_file = 1;
00414 
00415   *p_read_amount = nb_read;
00416 
00417   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);
00418 
00419 }
00420 #endif                          /* _FSAL_POSIX_USE_STREAM */
00421 
00445 #ifdef _FSAL_POSIX_USE_STREAM
00446 fsal_status_t POSIXFSAL_write(fsal_file_t * file_descriptor,     /* IN */
00447                               fsal_op_context_t * p_context,     /* IN */
00448                               fsal_seek_t * p_seek_descriptor,  /* IN */
00449                               fsal_size_t buffer_size,  /* IN */
00450                               caddr_t buffer,   /* IN */
00451                               fsal_size_t * p_write_amount      /* OUT */
00452     )
00453 {
00454 
00455   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00456   size_t nb_written;
00457   size_t i_size;
00458   int rc, errsv;
00459 
00460   /* sanity checks. */
00461   if(!p_file_descriptor || !buffer || !p_write_amount)
00462     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);
00463 
00464   if(p_file_descriptor->ro)
00465     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);
00466 
00468   i_size = (size_t) buffer_size;
00469 
00470   /* positioning */
00471 
00472   if(p_seek_descriptor)
00473     {
00474 
00475       switch (p_seek_descriptor->whence)
00476         {
00477         case FSAL_SEEK_CUR:
00478           /* set position plus offset */
00479 
00480           TakeTokenFSCall();
00481           rc = fseek(p_file_descriptor->p_file, p_seek_descriptor->offset, SEEK_CUR);
00482           errsv = errno;
00483           ReleaseTokenFSCall();
00484           break;
00485 
00486         case FSAL_SEEK_SET:
00487           /* set absolute position to offset */
00488 
00489           TakeTokenFSCall();
00490           rc = fseek(p_file_descriptor->p_file, p_seek_descriptor->offset, SEEK_SET);
00491           errsv = errno;
00492           ReleaseTokenFSCall();
00493 
00494           break;
00495 
00496         case FSAL_SEEK_END:
00497           /* set end of file plus offset */
00498 
00499           TakeTokenFSCall();
00500           rc = fseek(p_file_descriptor->p_file, p_seek_descriptor->offset, SEEK_END);
00501           errsv = errno;
00502           ReleaseTokenFSCall();
00503 
00504           break;
00505         }
00506 
00507       if(rc)
00508         {
00509 
00510           LogEvent(COMPONENT_FSAL,
00511                    "Error in posix fseek operation (whence=%s, offset=%lld)",
00512                    (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00513                     (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
00514                      (p_seek_descriptor->whence ==
00515                       FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
00516                    p_seek_descriptor->offset);
00517 
00518           Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00519 
00520         }
00521 
00522       LogFullDebug(COMPONENT_FSAL,
00523                    "Write operation (whence=%s, offset=%lld, size=%lld)",
00524                    (p_seek_descriptor->whence ==
00525                     FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence ==
00526                                                   FSAL_SEEK_SET ? "SEEK_SET"
00527                                                   : (p_seek_descriptor->whence ==
00528                                                      FSAL_SEEK_END ? "SEEK_END" :
00529                                                      "ERROR"))),
00530                    p_seek_descriptor->offset, buffer_size);
00531 
00532     }
00533 
00534   /* write operation */
00535 
00536   TakeTokenFSCall();
00537 
00538   nb_written = fwrite(buffer, 1, i_size, p_file_descriptor->p_file);
00539 
00540   /* With no flush, uncommited write may occur on 64 bits platforms */
00541   (void)fflush(p_file_descriptor->p_file);
00542 
00543   ReleaseTokenFSCall();
00544 
00547   if(nb_written <= 0 && ferror(p_file_descriptor->p_file))
00548     {
00549       Return(posix2fsal_error(EBADF), EBADF, INDEX_FSAL_write);
00550     }
00551 
00552   /* set output vars */
00553 
00554   *p_write_amount = (fsal_size_t) nb_written;
00555 
00556   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00557 
00558 }
00559 #else
00560 fsal_status_t POSIXFSAL_write(fsal_file_t * file_descriptor,     /* IN */
00561                               fsal_op_context_t * p_context,     /* IN */
00562                               fsal_seek_t * p_seek_descriptor,  /* IN */
00563                               fsal_size_t buffer_size,  /* IN */
00564                               caddr_t buffer,   /* IN */
00565                               fsal_size_t * p_write_amount      /* OUT */
00566     )
00567 {
00568 
00569   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00570   size_t i_size;
00571   size_t nb_written;
00572   int rc, errsv;
00573 
00574   /* sanity checks. */
00575   if(!p_file_descriptor || !buffer || !p_write_amount)
00576     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);
00577 
00579   i_size = (size_t) buffer_size;
00580 
00581   /* positioning */
00582 
00583   if(p_seek_descriptor)
00584     {
00585 
00586       switch (p_seek_descriptor->whence)
00587         {
00588         case FSAL_SEEK_CUR:
00589         case FSAL_SEEK_END:
00590           /* set position plus offset */
00591 
00592           TakeTokenFSCall();
00593           rc = lseek(p_file_descriptor->filefd, p_seek_descriptor->offset,
00594                      p_seek_descriptor->whence);
00595           errsv = errno;
00596 
00597           if(rc)
00598             {
00599               LogEvent(COMPONENT_FSAL,
00600                        "Error in posix fseek operation (whence=%s, offset=%"PRId64")",
00601                        (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
00602                         (p_seek_descriptor->whence ==
00603                          FSAL_SEEK_SET ? "SEEK_SET" : (p_seek_descriptor->whence
00604                                                        ==
00605                                                        FSAL_SEEK_END ? "SEEK_END"
00606                                                        : "ERROR"))),
00607                        p_seek_descriptor->offset);
00608 
00609               ReleaseTokenFSCall();
00610 
00611               Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
00612             }
00613 
00614           nb_written = write(p_file_descriptor->filefd, buffer, i_size);
00615 
00616           ReleaseTokenFSCall();
00617           break;
00618 
00619         case FSAL_SEEK_SET:
00620           /* set absolute position to offset */
00621 
00622           TakeTokenFSCall();
00623           nb_written =
00624               pwrite(p_file_descriptor->filefd, buffer, i_size,
00625                      p_seek_descriptor->offset);
00626           errsv = errno;
00627 
00628           ReleaseTokenFSCall();
00629 
00630           break;
00631         }
00632     }
00633   else
00634     {
00635       TakeTokenFSCall();
00636 
00637       nb_written = write(p_file_descriptor->filefd, buffer, i_size);
00638 
00639       ReleaseTokenFSCall();
00640     }
00641 
00643   if(nb_written == -1)
00644     Return(posix2fsal_error(EBADF), EBADF, INDEX_FSAL_write);
00645 
00646   *p_write_amount = nb_written;
00647 
00648   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
00649 
00650 }
00651 
00652 #endif                          /* _FSAL_POSIX_USE_STREAM */
00653 
00666 fsal_status_t POSIXFSAL_close(fsal_file_t * file_descriptor      /* IN */
00667     )
00668 {
00669   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00670   int rc, errsv;
00671 
00672   /* sanity checks. */
00673   if(!p_file_descriptor)
00674     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);
00675 
00676   /* call to close */
00677 
00678   TakeTokenFSCall();
00679 
00680 #ifdef _FSAL_POSIX_USE_STREAM
00681   rc = fclose(p_file_descriptor->p_file);
00682 #else
00683   rc = close(p_file_descriptor->filefd);
00684 #endif
00685 
00686   errsv = errno;
00687 
00688   ReleaseTokenFSCall();
00689 
00690   if(rc)
00691     Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_close);
00692 
00693   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);
00694 
00695 }
00696 
00697 unsigned int POSIXFSAL_GetFileno(fsal_file_t * pfile)
00698 {
00699   return ((posixfsal_file_t *)pfile)->filefd;
00700 }
00701 
00719 fsal_status_t POSIXFSAL_commit(fsal_file_t * file_descriptor,
00720                              fsal_off_t    offset, 
00721                              fsal_size_t   length )
00722 
00723 {
00724   posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor;
00725   int rc, errsv;
00726 
00727   /* sanity checks. */
00728   if(!p_file_descriptor)
00729     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_commit);
00730 
00731   /* Flush data. */
00732   TakeTokenFSCall();
00733   rc = fsync(p_file_descriptor->filefd);
00734   errsv = errno;
00735   ReleaseTokenFSCall();
00736   
00737   if(rc)
00738     {
00739       LogEvent(COMPONENT_FSAL, "Error in fsync operation");
00740       Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_commit);
00741     }
00742 
00743   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_commit);
00744 }