glibc源码逆向——fwrite函数

看着raycp师傅的文章分析,只剩最后两个函数了fwrite、fclose

源码样例

#include<stdio.h>
#include<stdlib.h>
int main(){
    char *data=malloc(0x1000);
    FILE*fp=fopen("test","wb");
    
    fwrite(data,1,0x30,fp);
    return 0;
}

源码分析

 进入fwrite看看

29    _IO_size_t
30    _IO_fwrite (const void *buf, _IO_size_t size, _IO_size_t count, _IO_FILE *fp)
31    {
32      _IO_size_t request = size * count;
33      _IO_size_t written = 0;
34      CHECK_FILE (fp, 0);
35      if (request == 0)
36        return 0;
37      _IO_acquire_lock (fp);
38      if (_IO_vtable_offset (fp) != 0 || _IO_fwide (fp, -1) == -1)
39        written = _IO_sputn (fp, (const char *) buf, request);
40      _IO_release_lock (fp);
41      /* We have written all of the input in case the return value indicates
42         this or EOF is returned.  The latter is a special case where we
43         simply did not manage to flush the buffer.  But the data is in the
44         buffer and therefore written as far as fwrite is concerned.  */
45      if (written == request || written == EOF)
46        return count;
47      else
48        return written / size;
49    }
50    libc_hidden_def (_IO_fwrite)

 函数通过简单的检查后,就进入了_IO_sputn函数

1278    _IO_size_t
1279    _IO_new_file_xsputn (_IO_FILE *f, const void *data, _IO_size_t n)
1280    {
1281      const char *s = (const char *) data;
1282      _IO_size_t to_do = n;
1283      int must_flush = 0;
1284      _IO_size_t count = 0;
1285    
1286      if (n <= 0)
1287        return 0;
1288      /* This is an optimized implementation.
1289         If the amount to be written straddles a block boundary
1290         (or the filebuf is unbuffered), use sys_write directly. */
1291    
1292      /* First figure out how much space is available in the buffer. */
1293      if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
1294        {
1295          count = f->_IO_buf_end - f->_IO_write_ptr;
1296          if (count >= n)
1297        {
1298          const char *p;
1299          for (p = s + n; p > s; )
1300            {
1301              if (*--p == '\n')
1302            {
1303              count = p - s + 1;
1304              must_flush = 1;
1305              break;
1306            }
1307            }
1308        }
1309        }
1310      else if (f->_IO_write_end > f->_IO_write_ptr)
1311        count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
1312    
1313      /* Then fill the buffer. */
1314      if (count > 0)
1315        {
1316          if (count > to_do)
1317        count = to_do;
1318    #ifdef _LIBC
1319          f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
1320    #else
1321          memcpy (f->_IO_write_ptr, s, count);
1322          f->_IO_write_ptr += count;
1323    #endif
1324          s += count;
1325          to_do -= count;
1326        }
1327      if (to_do + must_flush > 0)
1328        {
1329          _IO_size_t block_size, do_write;
1330          /* Next flush the (full) buffer. */
1331          if (_IO_OVERFLOW (f, EOF) == EOF)
1332        /* If nothing else has to be written we must not signal the
1333           caller that everything has been written.  */
1334        return to_do == 0 ? EOF : n - to_do;
1335    
1336          /* Try to maintain alignment: write a whole number of blocks.  */
1337          block_size = f->_IO_buf_end - f->_IO_buf_base;
1338          do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
1339    
1340          if (do_write)
1341        {
1342          count = new_do_write (f, s, do_write);
1343          to_do -= count;
1344          if (count < do_write)
1345            return n - to_do;
1346        }
1347    
1348          /* Now write out the remainder.  Normally, this will fit in the
1349         buffer, but it's somewhat messier for line-buffered files,
1350         so we let _IO_default_xsputn handle the general case. */
1351          if (to_do)
1352        to_do -= _IO_default_xsputn (f, s+do_write, to_do);
1353        }
1354      return n - to_do;
1355    }
1356    libc_hidden_ver (_IO_new_file_xsputn, _IO_file_xsputn)

 由于还没对缓冲区进行初始化_IO_write_base、_IO_write_ptr、_IO_write_end、_IO_buf_base、_IO_buf_end都是0,所以需要对其进行初始化,所以进入了这里,我们跟进_IO_doallocbuf看一看

818     if (f->_IO_write_base == NULL)
   819     {
   820       _IO_doallocbuf (f);
   821       _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
   822     }

_IO_doallocbuf函数

这个函数跟我们在fread里的函数是一样的,其主要作用是将_IO_buf_base、_IO_buf_end初始化,我们可以看下此时的f指针即可,接着进入了_IO_setg函数

 

 _IO_setg函数

 

posted @ 2021-01-15 18:38  PYozo_free  阅读(721)  评论(0编辑  收藏  举报