LCOV - code coverage report
Current view: directory - src/trusted/gio - gio_nacl_desc_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 159 113 71.1 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright 2010 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <stdio.h>
       8                 : #include <stdlib.h>
       9                 : 
      10                 : #if NACL_WINDOWS
      11                 : # include "io.h"
      12                 : # include "fcntl.h"
      13                 : #endif
      14                 : 
      15                 : #define COPY_CHUNKSIZE  (4 * 4096)
      16                 : 
      17                 : 
      18                 : /*
      19                 :  * cp via gio on top of NaClDescIoDesc, as a test.
      20                 :  */
      21                 : 
      22                 : #include "native_client/src/include/portability.h"
      23                 : 
      24                 : #include "native_client/src/shared/platform/nacl_check.h"
      25                 : #include "native_client/src/shared/platform/nacl_log.h"
      26                 : #include "native_client/src/shared/platform/nacl_time.h"
      27                 : #include "native_client/src/shared/platform/nacl_secure_random.h"
      28                 : #include "native_client/src/shared/platform/nacl_global_secure_random.h"
      29                 : 
      30                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      31                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      32                 : 
      33                 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
      34                 : 
      35                 : #include "native_client/src/trusted/desc/nrd_all_modules.h"
      36                 : #include "native_client/src/trusted/gio/gio_nacl_desc.h"
      37                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      38                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      39                 : 
      40                 : void Usage(void) {
      41               0 :   fprintf(stderr, "Usage: gio_nacl_desc_test src_file dst_file\n");
      42               0 : }
      43                 : 
      44             102 : int WriteAll(struct Gio *dst, char *buffer, size_t nbytes) {
      45             102 :   size_t bytes_written;
      46             102 :   ssize_t written;
      47             102 :   int num_errors = 0;
      48                 : 
      49             306 :   for (bytes_written = 0;
      50                 :        bytes_written < nbytes;
      51             102 :        bytes_written += written) {
      52             102 :     written = (*NACL_VTBL(Gio, dst)->Write)(dst,
      53                 :                                             buffer + bytes_written,
      54                 :                                             nbytes - bytes_written);
      55             102 :     if (written < 0) {
      56               0 :       written = 0;
      57               0 :       ++num_errors;
      58               0 :       fprintf(stderr, "Write error\n");
      59               0 :     }
      60             102 :   }
      61             102 :   return num_errors;
      62                 : }
      63                 : 
      64              68 : int ReadAll(struct Gio *src, char *buffer, size_t nbytes) {
      65              68 :   size_t bytes_read;
      66              68 :   ssize_t readden;  /* for parallelism :-) */
      67              68 :   int num_errors = 0;
      68                 : 
      69             204 :   for (bytes_read = 0;
      70                 :        bytes_read < nbytes;
      71              68 :        bytes_read += readden) {
      72              68 :     readden = (*NACL_VTBL(Gio, src)->Read)(src,
      73                 :                                            buffer + bytes_read,
      74                 :                                            nbytes - bytes_read);
      75              68 :     if (readden < 0) {
      76               0 :       readden = 0;
      77               0 :       ++num_errors;
      78               0 :       fprintf(stderr, "read error\n");
      79               0 :     }
      80              68 :   }
      81              68 :   return num_errors;
      82                 : }
      83                 : 
      84                 : /*
      85                 :  * Returns number of detected but correctable errors.
      86                 :  */
      87               1 : int GioCopy(struct Gio *src, struct Gio *dst) {
      88               1 :   char buffer[COPY_CHUNKSIZE];
      89               1 :   ssize_t bytes_read;
      90               1 :   int num_errors = 0;
      91                 : 
      92              36 :   while (0 != (bytes_read = (*NACL_VTBL(Gio, src)->
      93                 :                              Read)(src, buffer, sizeof buffer))) {
      94              34 :     if (bytes_read < 0) {
      95               0 :       fprintf(stderr, "negative read?!?\n");
      96               0 :       return ++num_errors;
      97                 :     }
      98              34 :     num_errors += WriteAll(dst, buffer, (size_t) bytes_read);
      99              34 :   }
     100               1 :   return num_errors;
     101               1 : }
     102                 : 
     103               2 : int ComparePosixFiles(char *file1, char *file2) {
     104               2 :   FILE *f1 = fopen(file1, "r");
     105               2 :   FILE *f2 = fopen(file2, "r");
     106               2 :   int num_errors = 0;
     107               2 :   int byte;
     108               2 :   int byte2;
     109                 : 
     110               2 :   if (NULL == f1) return 1;
     111               2 :   if (NULL == f2) return 1;
     112                 : 
     113         1099234 :   while (EOF != (byte = getc(f1))) {
     114         1099230 :     if (byte != (byte2 = getc(f2))) {
     115               0 :       ++num_errors;
     116               0 :     }
     117         1099230 :     if (EOF == byte2) {
     118               0 :       fprintf(stderr, "file length differs (%s short)\n", file2);
     119                 :       /* num_errors already incremented above */
     120               0 :       break;
     121                 :     }
     122         1099230 :   }
     123               2 :   if (EOF != getc(f2)) {
     124               0 :     fprintf(stderr, "file length differs (%s short)\n", file1);
     125               0 :     ++num_errors;
     126               0 :   }
     127               2 :   if (0 != num_errors) {
     128               0 :     fprintf(stderr, "files %s and %s differ\n", file1, file2);
     129               0 :   }
     130               2 :   return num_errors;
     131               2 : }
     132                 : 
     133               2 : void RemoveFile(char *fname) {
     134                 : #if NACL_WINDOWS
     135                 :   _unlink(fname);
     136                 : #else
     137               2 :   unlink(fname);
     138                 : #endif
     139               2 : }
     140                 : 
     141               2 : int GioRevCopy(struct Gio *src, struct Gio *dst) {
     142               2 :   off_t file_size;
     143               2 :   char buffer[COPY_CHUNKSIZE];
     144               2 :   off_t start_offset;
     145               2 :   int num_errors = 0;
     146               2 :   size_t expected_bytes;
     147                 : 
     148               2 :   file_size = (*NACL_VTBL(Gio, src)->Seek)(src, 0, SEEK_END);
     149               2 :   if (file_size <= 0) {
     150               0 :     fprintf(stderr, "non-positive file size?!?\n");
     151               0 :   }
     152                 : 
     153               2 :   start_offset = file_size;
     154               2 :   do {
     155              68 :     start_offset -= COPY_CHUNKSIZE;
     156              68 :     expected_bytes = COPY_CHUNKSIZE;
     157              68 :     if (start_offset < 0) {
     158               2 :       expected_bytes = start_offset + COPY_CHUNKSIZE;
     159               2 :       start_offset = 0;
     160               2 :     }
     161              68 :     if (start_offset != (*NACL_VTBL(Gio, src)->
     162                 :                          Seek)(src, start_offset, SEEK_SET)) {
     163               0 :       fprintf(stderr, "seek in source file failed, offset %"NACL_PRId64"\n",
     164                 :               (int64_t) start_offset);
     165               0 :       return ++num_errors;
     166                 :     }
     167              68 :     num_errors += ReadAll(src, buffer, expected_bytes);
     168              68 :     if (start_offset != (*NACL_VTBL(Gio, dst)->
     169                 :                          Seek)(dst, start_offset, SEEK_SET)) {
     170               0 :       fprintf(stderr, "seek in destination file failed, offset"
     171                 :               " %"NACL_PRId64"\n", (int64_t) start_offset);
     172               0 :       return ++num_errors;
     173                 :     }
     174              68 :     num_errors += WriteAll(dst, buffer, expected_bytes);
     175             136 :   } while (start_offset > 0);
     176                 : 
     177               2 :   return num_errors;
     178               2 : }
     179                 : 
     180               1 : int main(int ac,
     181               1 :          char **av) {
     182               1 :   struct NaClDescIoDesc *src;
     183               1 :   struct NaClDescIoDesc *dst;
     184               1 :   struct NaClGioNaClDesc gsrc;
     185               1 :   struct NaClGioNaClDesc gdst;
     186               1 :   int num_errors = 0;
     187                 : 
     188               1 :   if (ac != 3) {
     189               0 :     Usage();
     190               0 :     return -1;
     191                 :   }
     192                 : 
     193               1 :   NaClLogModuleInit();
     194               1 :   NaClTimeInit();
     195               1 :   NaClSecureRngModuleInit();
     196               1 :   NaClGlobalSecureRngInit();
     197                 : 
     198               1 :   src = NaClDescIoDescOpen(av[1], NACL_ABI_O_RDONLY, 0);
     199               1 :   if (NULL == src) {
     200               0 :     fprintf(stderr, "could not open %s for read\n", av[1]);
     201               0 :     Usage();
     202               0 :     return -2;
     203                 :   }
     204               1 :   dst = NaClDescIoDescOpen(av[2],
     205                 :                            NACL_ABI_O_WRONLY|
     206                 :                            NACL_ABI_O_TRUNC|
     207                 :                            NACL_ABI_O_CREAT,
     208                 :                            0666);
     209               1 :   if (NULL == dst) {
     210               0 :     fprintf(stderr, "could not open %s for write\n", av[2]);
     211               0 :     Usage();
     212               0 :     return -3;
     213                 :   }
     214               1 :   if (!NaClGioNaClDescCtor(&gsrc, (struct NaClDesc *) src)) {
     215               0 :     fprintf(stderr, "NaClGioNaClDescCtor failed for source file\n");
     216               0 :     return -4;
     217                 :   }
     218               1 :   if (!NaClGioNaClDescCtor(&gdst, (struct NaClDesc *) dst)) {
     219               0 :     fprintf(stderr, "NaClGioNaClDescCtor failed for destination file\n");
     220               0 :     return -5;
     221                 :   }
     222                 : 
     223                 :   /*
     224                 :    * The NaClGioNaClDesc now owns the NaClDescIoDesc.
     225                 :    */
     226               1 :   NaClDescUnref(&src->base);
     227               1 :   NaClDescUnref(&dst->base);
     228                 : 
     229               1 :   num_errors += GioCopy((struct Gio *) &gsrc, (struct Gio *) &gdst);
     230               1 :   num_errors += ComparePosixFiles(av[1], av[2]);
     231                 : 
     232               1 :   (*NACL_VTBL(Gio, &gdst)->Close)(&gdst.base);
     233               1 :   (*NACL_VTBL(Gio, &gdst)->Dtor)(&gdst.base);
     234                 : 
     235               1 :   if (0 < num_errors) {
     236               0 :     return num_errors;
     237                 :   }
     238                 : 
     239               1 :   RemoveFile(av[2]);
     240                 : 
     241                 :   /* reverse copy; reuse gsrc */
     242                 : 
     243               1 :   dst = NaClDescIoDescOpen(av[2],
     244                 :                            NACL_ABI_O_WRONLY|
     245                 :                            NACL_ABI_O_TRUNC|
     246                 :                            NACL_ABI_O_CREAT,
     247                 :                            0666);
     248               1 :   if (NULL == dst) {
     249               0 :     fprintf(stderr, "could not open %s for write\n", av[2]);
     250               0 :     Usage();
     251               0 :     return -6;
     252                 :   }
     253               1 :   if (!NaClGioNaClDescCtor(&gdst, (struct NaClDesc *) dst)) {
     254               0 :     fprintf(stderr, "NaClGioNaClDescCtor faied for destination file\n");
     255               0 :     return -7;
     256                 :   }
     257                 : 
     258               1 :   NaClDescUnref(&dst->base);
     259                 : 
     260                 :   /*
     261                 :    * We run GioRevCopy twice because if Seek failed to move the file
     262                 :    * pointer but reported the file size correctly, it would still
     263                 :    * result in a correct output.  By running it twice, the destination
     264                 :    * data is just overwritten if the implementation is correct, and if
     265                 :    * it isn't, we would end up with a file that is twice the source
     266                 :    * file size.
     267                 :    */
     268               1 :   num_errors += GioRevCopy((struct Gio *) &gsrc, (struct Gio *) &gdst);
     269               1 :   num_errors += GioRevCopy((struct Gio *) &gsrc, (struct Gio *) &gdst);
     270               1 :   num_errors += ComparePosixFiles(av[1], av[2]);
     271                 : 
     272               1 :   (*NACL_VTBL(Gio, &gdst)->Close)((struct Gio *) &gdst);
     273               1 :   (*NACL_VTBL(Gio, &gdst)->Dtor)((struct Gio *) &gdst);
     274                 : 
     275               1 :   (*NACL_VTBL(Gio, &gsrc)->Close)((struct Gio *) &gsrc);
     276               1 :   (*NACL_VTBL(Gio, &gsrc)->Dtor)((struct Gio *) &gsrc);
     277                 : 
     278               1 :   if (0 < num_errors) {
     279               0 :     return num_errors;
     280                 :   }
     281                 : 
     282               1 :   RemoveFile(av[2]);
     283                 : 
     284               1 :   return num_errors;
     285               1 : }

Generated by: LCOV version 1.7