openssl之BIO系列之11---檔案(file)型別BIO (轉)

worldblog發表於2007-12-14
openssl之BIO系列之11---檔案(file)型別BIO (轉)[@more@](file)型別BIO
 
 ---根據open doc/crypto/bio/bio_s_file.pod翻譯和自己的理解寫成
 
 (作者:DragonKing :wzhah@263 釋出於:之openssl專業論壇)
 
 前面我們已經介紹了很多BIO的基本構造和操作,現在,我們開始針對每一個型別BIO進行進一步的介紹,這些介紹都是基本基於openssl的幫助文件的,我儘可能加入自己的一些理解,理清思路。在開始這部分之前,我一直在想該從哪一種型別的BIO開始比較合適,因為這些BIO型別之間有些還是有相互聯絡的,比如BIO_s_bio型就和BIO_f_ssl有關係,最後,考慮到大家對檔案操作都比較熟悉,而且該型別BIO比較獨立,我決定從這個BIO開始介紹,隨後逐步介紹其它/sink型BIO,然後再介紹filter型BIO。
 
 檔案(file)型別BIO的相關和定義如下(opensslbio.h):
  BIO_METHOD * BIO_s_file(void);
  BIO *BIO_new_file(const char *filename, const char *mode);
  BIO *BIO_new_fp(FILE *stream, int flags);
 
  BIO_set_fp(BIO *b,FILE *fp, int flags);
  BIO_get_fp(BIO *b,FILE **fpp);
 
  int BIO_read_filename(BIO *b, char *name)
  int BIO_write_filename(BIO *b, char *name)
  int BIO_append_filename(BIO *b, char *name)
  int BIO_rw_filename(BIO *b, char *name)
 下面逐一介紹它們的作用和用法。
 【BIO_s_file】
 經過前面的介紹,大家應該對這種型別的函式結構很熟悉了,他們就是生成BIO型別的基本建構函式,BIO_s_file返回file型別的BIO,file型別的BIO封裝了一個標準的檔案結構,它是一種source/sink型BIO。file型別的BIO_METHOD結構定義如下:
 static BIO_METHOD methods_filep=
  {
  BIO_TYPE_FILE,
  "FILE pointer",
  file_write,
  file_read,
  file_puts,
  file_gets,
  file_ctrl,
  file_new,
  file_free,
  NULL,
  };
 可以看到,file型別的BIO定義了7個函式,這些函式的實現都在Cryptobiobss_file.c裡面,大家如果要了解該型別BIO的函式實現,可以參考該檔案。事實上,BIO_s_file只是簡單返回一個file型別的BIO_METHOD的結構的指標,其函式實現如下:
 BIO_METHOD *BIO_s_file(void)
  {
  return(&methods_filep);
  }
 其實,從這個結構可以略見BIO的實現的一班,即BIO的所有動作都是根據它的BIO_METHOD的型別(第一個引數)來決定它的動作和行為的,從而實現BIO對各種型別的多型實現。
 在file型別中,使用前面介紹過的BIO_read和BIO_write對底層的file資料流進行讀寫操作,file型別BIO是支援BIO_gets和BIO_puts函式的(大家如果忘了這些函式的作用,請參考前面的《BIO系列之6---BIO的IO操作函式》)。
 BIO_flush函式在file型別BIO中只是簡單了函式fflush。
 BIO_reset函式則將檔案指標重新指向檔案的開始位置,它呼叫fseek(stream,0,0)函式實現該功能。
 BIO_seek函式將檔案指標位置至於所定義的位置ofs上(從檔案開頭開始計算的偏移ofs),它呼叫了檔案的操作函式fseek(stream,ofs,0),是一個宏定義形式的函式,需要注意的是,因為該函式呼叫了fseek函式,所以成功的時候返回0,失敗的時候返回-1,這是跟標準BIO_seek函式定義不一樣的,因為標準的定義是成功返回1,失敗返回非正值。
 BIO_eof呼叫了feof函式。
 如果在BIO結構中設定了BIO_CLOSE的標誌,則在BIO釋放的時候會自動呼叫fclose函式。
 【BIO_new_file】
 該函式根據給定的mode型別建立了一個檔案BIO,mode引數的函式跟fopen函式中mode引數的含義是一樣的。返回的BIO設定了BIO_CLOSE標誌。呼叫成功返回一個BIO,否則返回NULL。
 事實上,該函式先呼叫了fopen函式開啟一個檔案,然後呼叫BIO_new函式建立一個file型別BIO,最後呼叫函式BIO_set_fp函式給BIO結構跟相關的file幫定。
 【BIO_new_fp】
 用檔案描述符建立一個file型別BIO,引數Flags可以為BIO_CLOSE,BIO_NOCLOSE(關閉標誌)以及BIO_FP_TEXT(將檔案設定為文字,預設的是二進位制模式,該選項只對平臺有效)。事實上,該函式呼叫BIO_new函式建立一個file型別BIO,然後呼叫函式BIO_set_fp函式給BIO結構跟相關的file幫定。需要注意的是,如果下層封裝的是stdout,stdin和stderr,他們因為跟一般的是不關閉的,所以應該設定BIO_NOCLOSE標誌。呼叫成功返回一個BIO,否則返回NULL。
 【BIO_set_fp】
 該函式將BIO跟檔案描述符fp幫定在一起,其引數flags的含義跟BIO_new_fp是一樣的。該函式是一個宏定義函式。呼叫成功返回1,否則返回0,不過目前的實現是從來不會出現失敗情況的。
 【BIO_get_fp】
 該函式返回file型別BIO中檔案描述符,也是一個宏定義。呼叫成功返回1,否則返回0,不過目前的實現是從來不會出現失敗情況的。
 【BIO_tell】
 返回位置指標的值。是一個宏定義函式。
 【BIO_read_filename, BIO_write_filename, BIO_append_filename, BIO_rw_filename】
 這四個函式分別設定BIO的讀檔名,寫檔名,附加檔名以及讀寫的檔名。他們都是一些宏定義函式。呼叫成功返回1,否則返回0。
 
 從上面各函式的介紹可以看出,因為BIO呼叫了底層的各種操作函式,所以,如果底層函式的呼叫有任何異常,都會反映在BIO的呼叫上。
 下面舉幾個BIO檔案型別操作的簡單例子:
 1.最簡單的例項
 
  BIO *bio_out;
  bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
  BIO_printf(bio_out, "Hello Worldn");
 
 2.上述例子的另一種實現方法
 
  BIO *bio_out;
  bio_out = BIO_new(BIO_s_file());
  if(bio_out == NULL) /* 出錯*/
  if(!BIO_set_fp(bio_out, stdout, BIO_NOCLOSE)) /* 出錯則將檔案流定向到標準輸出*/
  BIO_printf(bio_out, "Hello Worldn");
 
 3.寫檔案操作
 
  BIO *out;
  out = BIO_new_file("filename.txt", "w");
  if(!out) /*出錯 */
  BIO_printf(out, "Hello Worldn");
  BIO_free(out);
 
 4.上述例子的另一種實現方法
 
  BIO *out;
  out = BIO_new(BIO_s_file());
  if(out == NULL) /* Error ... */
  if(!BIO_write_filename(out, "filename.txt")) /* Error ... */
  BIO_printf(out, "Hello Worldn");
  BIO_free(out);

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993285/,如需轉載,請註明出處,否則將追究法律責任。

相關文章