CRC(Cyclic Redundancy Check, 순환 중복 검사, 巡環重復檢査)

    CRC(Cyclic Redundancy Check, 순환 중복 검사, 巡環重復檢査)는 주로 통신에서 데이터가 손실 또는 변경없이 잘 전송되었는 지에 대한 정합성을 체크하기 위하여 사용되는 기법입니다. 가끔 압축파일(zip, rar)의 압축을 풀 때에 "CRC에러"가 발생하기도 하는 데, 이 또한 압축된 파일이 손상되었는 지를 CRC값으로 확인하기도 합니다. (이론적인 내용은 위키백과를 참고하세요.)

 

    CRC는 32bit, 16bit로 생성할 수 있습니다. 32 bit CRC는 2의 32제곱(4,294,967,296: 약 43억) 가지의 경우를 가지며, 이 값은 1비트라도 다르면 값이 완전히 다른 값을 가집니다. 즉, 데이터는 비슷하더라도 CRC값은 완전히 다른 값을 가집니다. 이 특성을 잘 활용하면 데이터를 비슷한 비율로(분포도가 좋은) 분산하는 용도로 사용할 수 있습니다. 

 

예를들면, 

1. Hashtable / HashMap을 구현시에 key의 hash값을 생성하여 사용할 수 있습니다.을 분산하거나,

   Hashtable의 크기로 할당했을 때 CRC값을 1024로 나눈 나머지(CRC값 % 1024)로 하여 사용한든지....

2. 수백만, 수천만개의 파일을 하나의 디렉토리에 저장하면 access하는 데, 많은 시간이 걸리므로 하위 디렉토리를 만들어 분산해야 하는 경우 ABC... 순서로 하게되면 특정 문자로 시작하는 파일이 많아서 한쪽으로 몰리게 됩니다. 이 경우에 CRC값을 구한 후에 분산하려는 디렉토리 갯수로 나눈 나머지로 분산하면 거의 비슷한 비율로 분산됩니다.    

 


 

소스구현 (CRC32 소스) 

static const unsigned int crc32_tab[] = {
         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
         0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
         0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
         0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
         0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
         0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
         0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
         0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
         0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
         0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
         0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
         0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
         0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
         0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
         0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
         0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
         0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
         0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
         0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
         0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
         0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
         0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
         0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
         0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
         0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
         0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
         0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
         0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
         0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
         0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
         0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
         0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
         0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
         0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
         0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
         0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
         0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
         0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
         0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};


/*
* crc32()는 CRC32 값을 구하는 함수
*
* 파라미터:
*   crc : 처음 호출할 때에는 0, 데이터가 길어서 이어서 호출할 경우에는 이전에 return된 CRC값
*   buf : CRC값을 구할 데이터
*   size : buf의 크기
*
* return : CRC값
*/
unsigned int crc32(unsigned int crc, const void *buf, unsigned int size)
{
    const unsigned char *p = buf;

    crc = ~crc;
    
    while (size--)
    {
        crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
    }
    return crc ^ ~0U;
}

crc32.c
0.00MB

 

 

소스구현 (CRC16 소스) 

static unsigned short crc16_tab[256] = {
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};


/*
* crc16()은 CRC16 값을 구하는 함수
*
* 파라미터:
*   crc : 처음 호출할 때에는 0, 데이터가 길어서 이어서 호출할 경우에는 이전에 return된 CRC값
*   buf : CRC값을 구할 데이터
*   size : buf의 크기
*
* return : CRC값
*/
unsigned short crc16(unsigned short crc, const void *buf, unsigned int size)
{
    const unsigned char *p = buf;

    while (size--)
    {
        crc = crc16_tab[(crc ^ (*p++)) & 0xFF] ^ (crc >> 8);
    }

    return crc;
}

crc16.c
0.00MB

 

 


활용 예제

 

CRC의 주 목적인 데이터의 정합성 체크를 활용하는 예제입니다. 

두 개의 시스템이 있는 데, 양쪽의 시스템에 아주 크고 많은 파일들이 있습니다. 그런데, 이 파일들은 같은 구조로 파일들이 저장되고 있고, 파일들은 수정이 일어날 수도 있습니다. 양쪽 시스템의 파일 중, 서로 다른 파일들만 가려내고 싶습니다. 이런 경우 어떻게 하면 될까요?

   일반적으로 파일의 내용이 같은 지 확인을 하기 위해서는 두 파일을 열어서 같은 양을 읽은 후에 내용이 같은 지를 비교하면 됩니다. 그러나, 시스템이 떨어져 있어서 파일을 동시에 열어서 비교할 수 없다면, 파일 내용에 대한 CRC 값을 구해서 비교하면 됩니다.

 

아래의 예제는 특정 디렉토리 하위에 있는 모든 디렉토리를 뒤져서 파일정보와 파일 내용의 CRC값을 CSV파일로 만들어 주는 프로그램입니다. 양쪽 시스템에서 아래의 프로그램을 실행하여 csv 파일을 취합하여 excel의 VLOOKUP 등으로 파일명으로 mapping후에 CSV 파일을 비교하는 수작업을 좀 하거나 주기적으로 작업을 해야 한다면, 비교하는 별도의 프로그램을 작성하는 것이 좋겠습니다.  

 

#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>

static const unsigned int crc32_tab[] = {
         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
         0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
         0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
         0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
         0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
         0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
         0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
         0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
         0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
         0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
         0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
         0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
         0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
         0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
         0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
         0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
         0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
         0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
         0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
         0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
         0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
         0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
         0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
         0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
         0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
         0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
         0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
         0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
         0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
         0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
         0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
         0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
         0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
         0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
         0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
         0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
         0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
         0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
         0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

/*
* crc32()는 CRC32 값을 구하는 함수
*
* 파라미터:
*   crc : 처음 호출할 때에는 0, 데이터가 길어서 이어서 호출할 경우에는 이전에 return된 CRC값
*   buf : CRC값을 구할 데이터
*   size : buf의 크기
*
* return : CRC값
*/
unsigned int crc32(unsigned int crc, const void *buf, unsigned int size)
{
    const unsigned char *p = buf;

    crc = ~crc;
    while (size--)
    {
        crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
    }
    return crc ^ ~0U;
}

/*
* 파일의 내용에 대한 CRC32값을 return하는 함수
* CRC값이 같으면, 파일의 내용이 다를 확율은 약 43억분의 1이므로 내용은 같다고 볼 수 있다.
*/
unsigned int get_file_crc32(const char *filename)
{
    FILE            *fp = NULL;
    char            buffer[4096];
    int             size;
    unsigned int    crc = 0;
    errno = 0;

    if((fp = fopen(filename, "r")) == NULL)
    {
        return -1;
    }

    while((size = fread(buffer, 1, 4096, fp)) > 0)
    {
        crc = crc32(crc, buffer, size);
    }
    fclose(fp);

    return crc;
}

int create_file_info(FILE *fp, const char *path)
{
    DIR *  dir_ptr      = NULL;
    struct dirent *file = NULL;
    struct stat   buf;
    char   filename[1024];


    /* 목록을 읽을 디렉토리명으로 DIR *를 return 받습니다. */
    if((dir_ptr = opendir(path)) == NULL)
    {
        return -1;
    }

    /* 디렉토리의 처음부터 파일 또는 디렉토리명을 순서대로 한개씩 읽습니다. */
    while((file = readdir(dir_ptr)) != NULL)
    {
        // readdir 읽혀진 파일명 중에 현재 디렉토리를 나타네는 . 도 포함되어 있으므로
        // 무한 반복에 빠지지 않으려면 파일명이 . 이면 skip 해야 함
        if(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
        {
             continue;
        }

        sprintf(filename, "%s/%s", path, file->d_name);

        /* 파일의 속성(파일의 유형, 크기, 생성/변경 시간 등을 얻기 위하여 */
        if(stat(filename, &buf) == -1)
        {
            continue;
        }

        if(S_ISDIR(buf.st_mode))  // 검색된 이름의 속성이 디렉토리이면
        {
            /*
            * 검색된 파일이 directory이면 재귀호출로 하위 디렉토리를 다시 검색
            */
            create_file_info(fp, filename);
        }
        else if(S_ISREG(buf.st_mode)) // 검색된 이름의 속성이 일반파일이면
        {
            /*
            * 파일 정보를 CSV 형태로 출력함
            * 파일명, path/파일명, 파일크기, CRC32값
            */
            fprintf(fp, "%s,%s,%d,%u\n", file->d_name, filename, buf.st_size, get_file_crc32(filename));
        }
    }

    /* open된 directory 정보를 close 합니다. */
    closedir(dir_ptr);

    return 0;
}

int help(int argc, char **argv)
{
    printf("사용법:\n");
    printf("%s [dir] [csv파일명]\n", argv[0]);
    printf("\tdir : CRC값을 생성할 디렉토리 위치\n");
    printf("\t\t- 이 디렉토리 하위의 모든 파일의 CRC값을 생성하게 됨\n");
    printf("\tcsv파일명 : CRC 및 파일의 정보를 저장할 CSV파일명\n");
    printf("\t\t-설정하지 않으면 표준출력(화면)으로 출력됨\n");

    return 0;
}

int main(int argc, char **argv)
{
    FILE *fp = stdout;

    if(argc == 1)
    {
        return help(argc, argv);
    }

    if(argc == 3)
    {
        if((fp = fopen(argv[2], "r")) == NULL)
        {
            fprintf(stderr, "%s file open error: %s\n", argv[2], strerror(errno));
            return 1;
        }
    }

    create_file_info(fp, argv[1]);

    if(argc == 3)
    {
        fclose(fp);
    }

    return 0;
}

all_file_crc32.c
0.01MB

블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

Tag , , ,

댓글을 달아 주세요