zoukankan      html  css  js  c++  java
  • 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 == '
    ')
    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函数

  • 相关阅读:
    elasticsearch操作命令
    mysql-清除binlog日志命令
    TensorFlow 基础 (03)
    TensorFlow 基础 (02)
    TensorFlow 基础 (01)
    Python 基础练手 32 道
    Pandas 批量处理文本表
    Pandas 清除 Excel 特殊字符
    MNIST实例-Tensorflow 初体验
    字符串和文本 (02)
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/14283687.html
Copyright © 2011-2022 走看看