Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/lib/sendfile.c

    r740 r988  
    3434#endif
    3535
    36 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
     36ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count)
    3737{
    3838        size_t total=0;
     
    5959                ssize_t nwritten;
    6060                do {
    61 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
    62                         nwritten = sendfile64(tofd, fromfd, &offset, total);
    63 #else
    6461                        nwritten = sendfile(tofd, fromfd, &offset, total);
    65 #endif
    66 #if defined(EWOULDBLOCK)
    6762                } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
    68 #else
    69                 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN));
    70 #endif
    7163                if (nwritten == -1) {
    7264                        if (errno == ENOSYS || errno == EINVAL) {
     
    9486}
    9587
    96 #elif defined(LINUX_BROKEN_SENDFILE_API)
    97 
    98 /*
    99  * We must use explicit 32 bit types here. This code path means Linux
    100  * won't do proper 64-bit sendfile. JRA.
    101  */
    102 
    103 extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count);
    104 
    105 
    106 #ifndef MSG_MORE
    107 #define MSG_MORE 0x8000
    108 #endif
    109 
    110 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
    111 {
    112         size_t total=0;
    113         ssize_t ret;
    114         ssize_t hdr_len = 0;
    115         uint32 small_total = 0;
    116         int32 small_offset;
    117 
    118         /*
    119          * Fix for broken Linux 2.4 systems with no working sendfile64().
    120          * If the offset+count > 2 GB then pretend we don't have the
    121          * system call sendfile at all. The upper layer catches this
    122          * and uses a normal read. JRA.
    123          */
    124 
    125         if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) {
    126                 errno = ENOSYS;
    127                 return -1;
    128         }
    129 
    130         /*
    131          * Send the header first.
    132          * Use MSG_MORE to cork the TCP output until sendfile is called.
    133          */
    134 
    135         if (header) {
    136                 hdr_len = header->length;
    137                 while (total < hdr_len) {
    138                         ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
    139                         if (ret == -1)
    140                                 return -1;
    141                         total += ret;
    142                 }
    143         }
    144 
    145         small_total = (uint32)count;
    146         small_offset = (int32)offset;
    147 
    148         while (small_total) {
    149                 int32 nwritten;
    150                 do {
    151                         nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
    152 #if defined(EWOULDBLOCK)
    153                 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
    154 #else
    155                 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN));
    156 #endif
    157                 if (nwritten == -1) {
    158                         if (errno == ENOSYS || errno == EINVAL) {
    159                                 /* Ok - we're in a world of pain here. We just sent
    160                                  * the header, but the sendfile failed. We have to
    161                                  * emulate the sendfile at an upper layer before we
    162                                  * disable it's use. So we do something really ugly.
    163                                  * We set the errno to a strange value so we can detect
    164                                  * this at the upper level and take care of it without
    165                                  * layer violation. JRA.
    166                                  */
    167                                 errno = EINTR; /* Normally we can never return this. */
    168                         }
    169                         return -1;
    170                 }
    171                 if (nwritten == 0) {
    172                         /*
    173                          * EOF, return a short read
    174                          */
    175                         return hdr_len + (((uint32)count) - small_total);
    176                 }
    177                 small_total -= nwritten;
    178         }
    179         return count + hdr_len;
    180 }
    181 
    182 
    18388#elif defined(SOLARIS_SENDFILE_API)
    18489
     
    18994#include <sys/sendfile.h>
    19095
    191 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
     96ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count)
    19297{
    19398        int sfvcnt;
     
    230135                xferred = 0;
    231136
    232 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64)
    233                         nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred);
    234 #else
    235137                        nwritten = sendfilev(tofd, vec, sfvcnt, &xferred);
    236 #endif
    237 #if defined(EWOULDBLOCK)
    238138                if  (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
    239 #else
    240                 if (nwritten == -1 && (errno == EINTR || errno == EAGAIN)) {
    241 #endif
    242139                        if (xferred == 0)
    243140                                continue; /* Nothing written yet. */
     
    279176#include <sys/uio.h>
    280177
    281 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
     178ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count)
    282179{
    283180        size_t total=0;
     
    308205
    309206                do {
    310 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
    311                         nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0);
    312 #else
    313207                        nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0);
    314 #endif
    315 #if defined(EWOULDBLOCK)
    316208                } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
    317 #else
    318                 } while (nwritten == -1 && (errno == EINTR || errno == EAGAIN));
    319 #endif
    320209                if (nwritten == -1)
    321210                        return -1;
     
    348237}
    349238
    350 #elif defined(FREEBSD_SENDFILE_API)
     239#elif defined(FREEBSD_SENDFILE_API) || defined(DARWIN_SENDFILE_API)
    351240
    352241#include <sys/types.h>
     
    354243#include <sys/uio.h>
    355244
    356 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
    357 {
    358         size_t total=0;
    359         struct sf_hdtr hdr;
    360         struct iovec hdtrl;
    361         size_t hdr_len = 0;
    362 
    363         hdr.headers = &hdtrl;
    364         hdr.hdr_cnt = 1;
    365         hdr.trailers = NULL;
    366         hdr.trl_cnt = 0;
    367 
    368         /* Set up the header iovec. */
    369         if (header) {
    370                 hdtrl.iov_base = (void *)header->data;
    371                 hdtrl.iov_len = hdr_len = header->length;
    372         } else {
    373                 hdtrl.iov_base = NULL;
    374                 hdtrl.iov_len = 0;
    375         }
    376 
    377         total = count;
    378         while (total + hdtrl.iov_len) {
    379                 SMB_OFF_T nwritten;
    380                 int ret;
    381 
    382                 /*
    383                  * FreeBSD sendfile returns 0 on success, -1 on error.
    384                  * Remember, the tofd and fromfd are reversed..... :-).
    385                  * nwritten includes the header data sent.
    386                  */
    387 
    388                 do {
    389                         ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0);
    390 #if defined(EWOULDBLOCK)
    391                 } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
     245ssize_t sys_sendfile(int tofd, int fromfd,
     246            const DATA_BLOB *header, off_t offset, size_t count)
     247{
     248        struct sf_hdtr  sf_header = {0};
     249        struct iovec    io_header = {0};
     250
     251        off_t   nwritten;
     252        int     ret;
     253
     254        if (header) {
     255                sf_header.headers = &io_header;
     256                sf_header.hdr_cnt = 1;
     257                io_header.iov_base = header->data;
     258                io_header.iov_len = header->length;
     259                sf_header.trailers = NULL;
     260                sf_header.trl_cnt = 0;
     261        }
     262
     263        while (count != 0) {
     264
     265                nwritten = count;
     266#if defined(DARWIN_SENDFILE_API)
     267                /* Darwin recycles nwritten as a value-result parameter, apart from that this
     268                   sendfile implementation is quite the same as the FreeBSD one */
     269                ret = sendfile(fromfd, tofd, offset, &nwritten, &sf_header, 0);
    392270#else
    393                 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
     271                ret = sendfile(fromfd, tofd, offset, count, &sf_header, &nwritten, 0);
    394272#endif
    395                 if (ret == -1)
    396                         return -1;
    397 
    398                 if (nwritten == 0)
    399                         return -1; /* I think we're at EOF here... */
    400 
    401                 /*
    402                  * If this was a short (signal interrupted) write we may need
    403                  * to subtract it from the header data, or null out the header
    404                  * data altogether if we wrote more than hdtrl.iov_len bytes.
    405                  * We change nwritten to be the number of file bytes written.
    406                  */
    407 
    408                 if (hdtrl.iov_base && hdtrl.iov_len) {
    409                         if (nwritten >= hdtrl.iov_len) {
    410                                 nwritten -= hdtrl.iov_len;
    411                                 hdtrl.iov_base = NULL;
    412                                 hdtrl.iov_len = 0;
     273                if (ret == -1 && errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) {
     274                        /* Send failed, we are toast. */
     275                        return -1;
     276                }
     277
     278                if (nwritten == 0) {
     279                        /* EOF of offset is after EOF. */
     280                        break;
     281                }
     282
     283                if (sf_header.hdr_cnt) {
     284                        if (io_header.iov_len <= nwritten) {
     285                                /* Entire header was sent. */
     286                                sf_header.headers = NULL;
     287                                sf_header.hdr_cnt = 0;
     288                                nwritten -= io_header.iov_len;
    413289                        } else {
    414                                 hdtrl.iov_base =
    415                                     (void *)((caddr_t)hdtrl.iov_base + nwritten);
    416                                 hdtrl.iov_len -= nwritten;
     290                                /* Partial header was sent. */
     291                                io_header.iov_len -= nwritten;
     292                                io_header.iov_base =
     293                                    ((uint8_t *)io_header.iov_base) + nwritten;
    417294                                nwritten = 0;
    418295                        }
    419296                }
    420                 total -= nwritten;
     297
    421298                offset += nwritten;
    422         }
    423         return count + hdr_len;
     299                count -= nwritten;
     300        }
     301
     302        return nwritten;
    424303}
    425304
     
    431310#include <sys/socket.h>
    432311
    433 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
     312ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count)
    434313{
    435314        struct sf_parms hdtrl;
     
    470349                do {
    471350                        ret = send_file(&tofd, &hdtrl, 0);
    472 #if defined(EWOULDBLOCK)
    473351                } while ((ret == 1) || (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)));
    474 #else
    475                 } while ((ret == 1) || (ret == -1 && (errno == EINTR || errno == EAGAIN)));
    476 #endif
    477352                if ( ret == -1 )
    478353                        return -1;
     
    485360#else /* No sendfile implementation. Return error. */
    486361
    487 ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
     362ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, off_t offset, size_t count)
    488363{
    489364        /* No sendfile syscall. */
Note: See TracChangeset for help on using the changeset viewer.