일단은 Subversion과 Trac을 설치하고 두개를 연동시켜 두었다. 커밋할 때 티켓 번호를 입력하지 않으면 커밋이 안되도록... 과거의 경험으로 볼 때 이건 필수 기능이다.
올 초에 trac을 설치했을 때, 강제성이 없었기 때문에 사용하지 않았던 실패경험이 있거든.

뭐... 사실 SVN도 파일서버처럼 쓰고 있기는 하지만, 내가 "하대리의 하루"라는 제목으로 세미나 한 번 하면 조금은 변하지 않을까? (어느 블로그에서 본 방법)

답답하다.

여기 와서 꽤 많은 변화를 시도하였는데 먹힌 것은 Beyond Compare 밖에 없다.

뭔가 새로운 것을 도입하려고 하면 귀찮게 왜자꾸 이러냐고 한다.
trac도, SVN도, 스토리보드, 짝 프로그래밍도 모두 실패했다.
혼자 시도하고 혼자 끝났다.

개발자는 보수적이라는 누군가의 말을 뼈져리게 느꼈다.
아마 노력없이 변화되는 것이 아니라면 절대 반겨주지 않을 것이다.

버뜨! 이번 만큼은 기필코 성공하고 말겠다!
만약 많은 수정사항들을 뭉뚱그려서 업데이트 하기 위해 티켓을 만든다면 해당 티켓을 없애서 SVN 저장소에 커밋을 못하도록 아예 막아버릴테다!

근데 나... 이렇게 프로그래밍 외적인 부분만 하고 있어도 되려나?
원래 개발환경은 한번 제대로 구축되면 손이 자주 안가야 하는건데, 이게 주가 된 느낌이다.
루비도, 코코아도, 맥루비도, 핫 코코아도, 아이폰도, 안드로이드도, LiMo도... 해보고 싶은 건 천지인데, 항상 마음만이다.

그렇게 하고 싶으면 집에 가서 하면 되잖아? -_-;

기본적인 파일 관리함수

 

int _access( const char *path, int mode );

 

파일을 엑세스 하기 전에 파일이 실제로 존재하는지 확인하는 함수입니다.

 

path : 조사할 파일의 경로

 

mode: 조사할 상태 지정 ( 0 은 존재, 2 는 쓰기, 4 는 읽기 )

 

return : 요청한 허가 상태를 가지면 0을 리턴, 그렇지 않으면 -1을 리턴

 

 

 

int remove( const char *path );

int _unlink( const char *filename );

 

위의 두 함수는 파일을 삭제 합니다.

 

path : 삭제하고자 하는 파일의 경로만 지정

 

 

 

int rename( const char *oldname, const char *newname );

 

이 함수는 파일의 이름을 변경합니다.

 

oldname : 변경하고자 하는 파일의 이름

 

newname : 새로 설정할 파일의 이름

 

 

 

int _chmod( const char *filename, int pmode );

 

파일의 속성을 변경 합니다.

 

pmode : _S_IWRITE  ,  _S_IREAD  둘중 하나를 주거나 둘다 줄수도 있음

 

 

파일검색 함수

 

long _findfirst( char *filespec, struct _finddata_t *fileinfo );

 

위의 함수로 첫번째 파일 검색 합니다.

 

int _findnext( long handle, struct _finddata_t *fileinfo );

 

위의 함수로 조건이 일치하는 다음 파일을 찾을수 있습니다.

 

int _findclose( long handle );

 

위의 함수로 모든 검색이 완료된 후 검색 핸들을 닫아 줍니다.

 

 

 

디렉토리 관리 함수

 

int _chdir( const char *dirname );

 

현제 작업중인 디렉토리의 경로 변경

 

char *_getcwd( char *buffer, int maxlen );

 

현재 작업 디렉토리를 조사

 

int _mkdir( const char *dirname );

 

디렉토리 생성

 

int _rmdir( const char *dirname );

 

디렉토리 제거

 

void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext );

 

경로 관리 함수로서  4개의 구분자로 분리한다.

 

void _makepath( char *path, const char *drive, const char *dir, const char *fname

                              , const char *ext );

 

경로 관리 함수로서 분리되어 있는 구분자를 합친다.

 

 

 

 

디스크 관리 함수

 

int _getdrive( void );

 

int _chdrive( int drive );

 

위의 두 함수는 작업 드라이브를 조사하거나 변경한다.


출처 : http://kin.naver.com/detail/detail.php?d1id=1&dir_id=10104&eid=4nUPmPpSlArMwqppck/df6nNQlKLaqFi&qb=tfC3usXkuK4gu+jBpiDH1Lz2&pid=fg9d8doi5ThssvOkpoZsss--248289&sid=ST9Q0woyP0kAAEgIOOk


C++ 을 하다보면 절대(순수?) 가상함수를 사용하게 되는 경우가 많다.
그런데 절대 가상함수를 상위에 선언은 해놓고 하위에서는 사용하지 않게 되는 인자가 생길 수 있는데, 이 때 컴파일러에서 뿌려주는 warning을 어떻게 처리해야 될까?

먼저 Visual C++에서는 #pragma warning를 통해 처리할 수 있다. (C4100이 사용되지 않은 인자 warning)


#pragma warning(disable:4100)
// warning 생기는 코드
#pragma warning(default:4100)

이것은 상당히 괜찮은 방법이다. 적어도 Visual C++에서 만큼은 이 warning이 생기지 않도록 해준다.
이건 많은 사람들이 잘 알고 있는 방법이고, 검색해도 이것이 주로 나온다.

그런데 구글 C++ 코딩 스타일 가이드를 보니 이 절대 가상함수 인자에 대해 나온 부분이 있었는데, 내가 왜 이런걸 몰랐나 싶은 생각이 들었다 ㅋㅋ

음... 내가 잘못봤나...?
지금 찾아보니까 또 안 보이네... 다른데서 봤나?

여튼 그 내용은 이랬다.(이랬던것 같다... ㅡㅡ;)


"절대 가상함수를 구현한 함수에서 해당 인자가 사용되지 않을 경우 변수 이름을 쓰지 않는다."

변수 이름을 쓰지 않는 이유는 첫째로 떠오르는 게 함수에서 참조되지 않는다는 것을 명시적으로 표현하는 것이다. 인자의 이름이 없으니 쓸 수가 없지!

그리고 확실하지 않은 두번째 이유는 바로 warning!

난 저런 경우에 warning 잡기 위한 노가다를 많이 해봐서 그런지 딱 보니 이게 제일 궁금했다.

"변수 이름이 없으면 warning을 어떻게 출력하지? 출력 안하지 않을까? 구글도 그런것을 고려해서 결정한 내용이 아닐까?"

훗~ 역시 해보니 warning이 뜨지 않는다.

물론 컴파일러마다 다를수도 있겠지만, 적어도 #pragma보다는 더 범용적이고 라인낭비를 줄이는 일일테지.

하나 배웠다.
다른 것 검색하다가 얻어걸린 것인데... 누가 친절히 번역해놓으셨다. ^^;
다 읽어보진 않았지만 정말 좋은 내용들이다.
나도 나만의 코딩 스타일이 있지만 얘들에 비하면 새발의 피로구나~

단순히 다른 기업의 코딩 스타일일 뿐인데 뭐가 그리 중요하다고 그러느냐는 사람들도 있겠다.
그런데 코딩 스타일을 보면 스타일은 물론이고 그 사람의 실력까지도 대충 짐작할 수 있다는 건 아는지?

코딩 스타일의 목적은 소스를 공유하는 사람들 사이의 가독성이 가장 크다고 하겠지만,
그 가독성을 위한 스타일을 정하기 전에 어떤 이유로 그 스타일을 정할 것인가?
스타일을 정하려면 타당한 이유가 있어야 하지 않겠어?
그런 것들에 관한 지식과 경험이 코딩 스타일에 그대로 녹아들어있다.

번역한 분이 쓰신 것처럼 Effective C++에 언급된 내용들을 고려한 흔적이 많이 보인다.
팀장님에게 이 중 몇가지만 추려서 우리 팀 코딩 스타일로 쓰자고 건의할까? ㅎㅎ
아직 팀에 코딩 스타일이 없다는 것은 문제라면 문제인데...
지금까지는 어차피 개인이 일하는 것이었으니까...

그래도 업무 인수인계할때라도 필요하지 않겠어?
그리고 SVN에 기능별로 쪼개서 자주 커밋한다면 업무인수인계할 때 정말 빠르게 습득할 수 있는데...
리비전별로 달라진 점과 무엇을 구현한건지 로그만 보면 금방인데 ㅋ

그러고보니 난 아직도 앞 사람이 했던 것을 모른다. (같이 근무한 적이 없다)
뭐 정보가 있어야지. 소스만 주면 단가?
STB 소스를 본다면 적어도 그 사람이 작성한 부분에 대해서 표시라도 해 놓던가... ㅡ_ㅡ;

팀내에 SVN의 활용이나 Beyond Compare 같은 소스 비교 툴을 전파시키고 싶은데 생각대로 되지 않는다.
SVN은 그냥 네트워크 폴더일 뿐이고, Beyond Compare는 나만 쓰는 프로그램.

단순히 글 하나 링크하는 것인데 말이 길어졌다. 맨날 이 꼬라지...
만약 링크한 글의 내용이 잘 이해되지 않는다면 스캇 마이어스의 [Effective C++]를 한번 읽어 본 후에
다시 읽어보기 바란다.

일단 용어 정리부터...
 
비밀키 : 일반적인 암호화에 사용되는 키. A와 B는 같은 비밀키를 공유해야 한다.
공개키 : 공개키 알고리즘에서 사용되는 키로 외부에 공개되는 키
개인키 : 공개키 알고리즘에서 사용되는 키로 개인이 소유하며 외부에 알려주지 않는 키
 
목적 - 공개키 알고리즘을 통해 비밀키를 생성하여 암호화에 사용한다.
 
DH 알고리즘의 핵심은 상대방의 공개키와 나의 개인키를 이용하여 계산을 하면 비밀키가 나온다는 것이다.
그 후 나와 상대방은 비밀키를 사용하여 데이터를 암호화한 후 전달하면 된다.
 
즉, AB 사이에서 사용할 비밀키를 생성하는 것을 식으로 나타내면 다음과 같다.
A의 비밀키 = A의 개인키 [DH연산] B의 공개키
B의 비밀키 B의 개인키 [DH연산] A의 공개키
그리고 A의 비밀키 = B의 비밀키 
 
위 DH연산을 사용하면 A의 비밀키와 B의 비밀키는 같은 값이 나오기 때문에 이것을 암호화에 사용할 수 있는 것이다.
그럼 DH에서 사용하는 연산은 이런 조건을 만족한다는 뜻인데 이 연산은 어떤 것일까?
 
여기서 이번엔 기호 정리...
 
p = DH연산에 사용되는 소수 (1024 bits 이상)
g = DH연산에 사용되는 베이스, 특별한 수. (x1의 값에 따라 나오는 개인키의 종류가 정해진 g는 사용할 수 없다)
s = 비밀키
 
A의 작업
========
1. 임의의 개인키 x1을 생성하고 다음의 식으로 공개키(y1)를 계산한다.
   y1 = gx1 mod p
2. B에게 자신의 공개키 y1을 전달한다.
B의 작업
========
3. 임의의 개인키 x2를 생성하고 다음의 식으로 공개키(y2)를 계산한다.
   y2 = gx2 mod p
4. 전달받은 A의 공개키(y1)와 자신의 개인키(x2)를 이용하여 비밀키(s)를 계산한다.
   s = y1x2 mod p
5. A에게 자신의 공개키 y2를 전달한다.
A의 작업
========
6. 전달받은 B의 공개키(y2)와 자신의 개인키(x1)를 이용하여 비밀키(s)를 계산한다.
   s = y2x1 mod p
 
위의 결과에서 보면 비밀키(s)가 같으려면 다음의 공식도 만족해야 한다.
   y1x2 mod p = y2x1 mod p
위 공식에 y1과 y2를 생성할 때 사용했던 계산식을 넣어보자.
   (gx1 mod p)x2 mod p = (gx2 mod p)x1 mod p
 
여기서 더 나아가려면 다른 것에 대해서 먼저 알아야되겠다.
((x mod p) * (y mod p)) mod p = xy mod p
 
따라서
(gx1 mod p)x2 mod p 는 (gx1)x2 mod p 가 되고
(gx2 mod p)x1 mod p 는 (gx2)x1 mod p 가 된다.
 
그럼 (gx1)x2 mod p = (gx2)x1 mod p 가 되는데, 이정도 왔으면 왜 같은지 알 것이다. ^^;;
지수승은 곱으로 대체할 수 있으니
gx1x2 mod p = gx2x1 mod p 가 된다.
 
끝났다! 

아.. 제길... 이거 쓴다고 야근한 꼴이 되는구나...
((x mod p) * (y mod p)) mod p = xy mod p
이거 증명하려다가 시간 다 보냈다.. ㅠ_ㅠ
결국 증명은 제외 ㅎㅎ


싸이 블로그 백업 [하지윤 2008.10.22 21:31]

// 상대방과 p와 g를 같은 값을 사용하고 상대방의 공개키를 알고 있는 상황
// p와 g와 자신의 개인키가 포함된 DH* pDH, 상대방의 공개키 BIGNUM* pPubKey
unsigned char abyKey[128]; // 128bit 키라면...
DH_compute_key(abyKey, pPubKey, pDH);


싸이 블로그 백업 [하지윤 2008.10.22 18:08]

// pDH에 이미 pDH->p, pDH->g가 세팅되어 있어야 함.
DH_generate_key(pDH);
// pDH->pub_key, pDH->pri_key 사용


싸이 블로그 백업 [하지윤 2008.10.22 18:00]

int nDHRet = DH_generate_parameters_ex(pDH, 1024, DH_GENERATOR_2, &g_cb); // 1024 bit에 g는 2로 생성.
if(!DH_check(pDH, &nDHRet))
{
   return;
}
if(nDHRet & DH_CHECK_P_NOT_PRIME)
   printf("p value is not prime\n");
if(nDHRet & DH_CHECK_P_NOT_SAFE_PRIME)
   printf("p value is not a safe prime\n");
if(nDHRet & DH_UNABLE_TO_CHECK_GENERATOR)
   printf("unable to check the generator value\n");
if(nDHRet & DH_NOT_SUITABLE_GENERATOR)
   printf("the g value is not a generator\n");
if(nDHRet == 0)
   printf("DH parameters appear to be ok.\n");

int nPBits = BN_num_bits(pDH->p); // p의 bit 크기 : 1024
int nGBits = BN_num_bits(pDH->g); // g의 bit 크기 : 2 (g가 5일땐 3)


싸이 블로그 백업 [하지윤 2008.10.22 17:55]

#include <io.h> 
 
// "C:\\SourceFolder\\*.*" 같은 형식의 pchFind
functionA(char* pchFind)
{
   struct _finddata_t findData;
   long find_seek = (long)_findfirst(pchFind, &findData );
   while(-1 != find_seek)
   {
      if(strcmp(findData.name, ".") != 0 && strcmp(findData.name, "..") != 0)
      {
         // findData.name 에 파일이름으로 데이터 처리
      }
   }while(_findnext(find_seek, &findData) != -1);
   _findclose(find_seek);
}


싸이 블로그 백업 [하zi 2008.10.17 11:32]

정리 차원에서 쓴다.
MAC Address 가져오는 방법.
이것을 사용해서 Ethernet인 경우의 MAC address만 출력하는 소스.
급조한것이긴 하지만 개발중인 소스를 올릴수는 없지 않은가? ㅡㅡ;;
PrintToHex은 당연히 데이터를 HEX 로 찍는 함수다.


#include <IPHlpApi.h>
#pragma comment(lib, "iphlpapi.lib")

IP_ADAPTER_INFO
*
GetNetworkAdaptersInfo()
{
   DWORD dwBufLen = 0;
   DWORD dwStatus = GetAdaptersInfo(NULL, &dwBufLen);
   ASSERT(dwStatus == ERROR_BUFFER_OVERFLOW);
   IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*)malloc(dwBufLen);
   dwStatus = GetAdaptersInfo(pAdapterInfo, &dwBufLen);
   assert(dwStatus == ERROR_SUCCESS);
   if(dwStatus != ERROR_SUCCESS)
   {
      free(pAdapterInfo);
      return NULL;
   }
   return pAdapterInfo;
}
 
void main()
{
   IP_ADAPTER_INFO* pAdaptersInfoList = GetNetworkAdaptersInfo();
   IP_ADAPTER_INFO* pAdapterInfo = pAdaptersInfoList;
   while(NULL != pAdapterInfo)
   {
      if(MIB_IF_TYPE_ETHERNET == pAdapterInfo->Type) // Ethernet == 6
      {
         PrintToHex(pAdapterInfo->Address, pAdapterInfo->AddressLength);
      }
      pAdapterInfo = pAdapterInfo->Next;
   }
   free(pAdaptersInfoList);
}
 
수정을 여기서 직접 해서 돌려보진 못했는데... 돌아가겠지? ㅡㅡ;


싸이 블로그 백업 [하zi 2008.09.18 14:20]

+ Recent posts