      SUBROUTINE GRIB_OPEN(kunit, cdfilnam, cdmode, 
     $                     kinfo, kinfo_len, kret)

      implicit none

c
c***  SUBROUTINE GRIB_OPEN(kunit, cdfilnam, cdmode, kinfo, kinfo_len, kret)
c
c     Sami Saarinen, ECMWF, 27/11/95
c
c     Mofifications
c     Pedro Viterbo, ECMWF,  9/01/2005   Handle files with different grib lengths
c   
c***  Purpose:
c
c     To open GRIB file for read/write or append
c
c***  Externals:
c
c     PBOPEN      - Opens file (via pbio)
c     GRIB_STAT   - Gets GRIB-file length in bytes
c
c***  Notes:
c
c     Coded in Fortran-90
c
c***  Input variables
      character*(*), intent(in) :: cdfilnam ! Filename
      character*(*), intent(in) :: cdmode   ! Open mode: 'r'=read, 
                                            ! 'w'=write, 'a'=append
      integer, intent(in)  :: kinfo_len     ! Length of the info vector
c***  Output variables
      integer, intent(out) :: kunit         ! PBIO file pointer
      integer, intent(out) :: kret          ! Return code
                                            !  0 = OK
                                            ! -1 = Couldn't open file
                                            ! -2 = Invalid file name
                                            ! -3 = Invalid open mode
                                            ! -4 = Invalid GRIB-file
      integer, intent(out) :: 
     $     kinfo(kinfo_len)     ! Information vector (if mode='r')
c-----------------------------------------------------------------------
! === END OF INTERFACE BLOCK ===

      logical ll_open_read, ll_buffer_data, ll_file_exist
      integer iret_pbio, ifile_size, itotl
      integer pbgtotl
      external pbgtotl

c-----------------------------------------------------------------------
c
c     1. Determine the open mode and open the file
c

      ll_open_read = (cdmode(1:1) == 'r' .or. cdmode(1:1) == 'R')

      if (ll_open_read .and. kinfo_len > 0)     kinfo(:) = 0

      if (ll_open_read) then
         inquire(file=cdfilnam, exist=ll_file_exist)
         if (.not. ll_file_exist) then
            kret = -1
            return
         endif
      endif

      call PBOPEN(kunit, cdfilnam, cdmode(1:1), iret_pbio)
      kret = iret_pbio

      if (len_trim(cdmode) > 1) then
         ll_buffer_data = (cdmode(2:2) == 'B')
         if (ll_buffer_data) then
            if (ll_open_read) then
               call UTIL_STAT(kunit, ifile_size)
               call UTIL_ALLOC_IOBUF(kunit, ifile_size, iret_pbio)
            else
               call UTIL_ALLOC_IOBUF(kunit, -1, iret_pbio)
            endif
            kret = iret_pbio
         endif
      else
         ll_buffer_data = .FALSE.
      endif

c-----------------------------------------------------------------------
c
c     2. Get some (advance) information to aid memory allocation etc.
c        ------------------------------------------------------------
c

      if (kret == 0 .and. ll_open_read .and. kinfo_len > 0) then
         call GRIB_INFO(kunit, kinfo, kinfo_len, kret)

         itotl=PBGTOTL(cdfilnam)
         kinfo(9)=itotl

         call GRIB_REWIND(kunit, iret_pbio)
      endif

      return
      END

