2014년 10월 21일 화요일

Vim 파일 저장 오류 __ 6

open() 함수가 실패했을 때, 어떤 에러가 발생하는지도 확인해 봐야 할 듯해서...

open()의 help
함수 실패시의 리턴값은 -1이고 조금 더 자세한 에러 원인을 알기 위해서는 errno 변수를 확인해 봐야 한다.
errno 값에 대해서 조금 더 확인해 보면,
errno의 help

help화면엔 별것이 없고, ERRNO.H를 열어 보자.
ERRNO.H

그럼, 이제 소스를 고쳐서 errno를 확인해 보기로 하자.

FILEIO.C 메시지에 errno 추가

make

디버그메시지, errno = 19

errno = 19는 EINVAL

결론은 Invalid Argument...휴..

Fileio.c의 mch_open()의 인자들을 모두 확인해 보았고, 두번째 인자들의 flag들도 바꾸어 보았으나 문제가 해결되지 않았다.
비록 에러코드는 Invalid Argument 이지만, 더 low-level에서의 인자를 뜻하는 것이 아닐런지...

인자들만 바꾸어서 문제가 해결된다면, 앞서의 mode와 마찬가지로 UNIX/Windows 차이가 발생할리 없었을 것이다.

지금까지의 시험결과로는 DOSBox 내부에서 문제를 해결하는 것이 불가능해 보인다.
DOSBox와 UNIX 사이의 interface, 특히 파일시스템과 관련된 interface의 문제로 보인다.

문제는 이런 경우의 디버깅이 매우 어렵다는 점....

Vim 파일 저장 오류 __ 5

Borland C++의 매뉴얼은 워낙에 구석기 유물인지 찾기가 곤란...
그래서 BC++ IDE의 Help를 활용하기로 했다.

Borland C++ IDE help

_chmod()의 도움말 화면
_chmod의 help

두번째 인자 func가 0이면 get, 1이면 set 기능을 하게 된다.
_chmod의 help (계속)

세번째 인자인 DOS file-attribute는 다음과 같다.
file attribute
실제 값을 확인하기 위해서 DOS.H를 확인해 보았다.
DOS.H
여기서 지난번에 추가한 디버그 메시지를 다시 확인해 보자.
추가했던 디버그 메시지
위의 메시지에서 p=32(0x20)은 mch_open()에서 세번째 인자로 사용될 perm이라는 변수에 할당된 값이며, _chmod() 함수를 이용해 얻은 값이다.
즉, 변수의 이름은 UNIX 파일 시스템의 권한(permission)을 의미하는 듯이 보이지만, MS-DOS 파일 시스템에서는 권한이라는 것이 없기에 파일의 속성만을 나타내고 있는 것이다.

다시 한번 에러가 발생한 부분의 code를 살펴보자.
FILEIO.C
위의 mch_open()이 실패한 것이 문제였고, mch_open()의 세번째 인자로 perm 변수를 사용하고 있음을 볼 수 있다.
하지만 이 소스만 보아도 문제의 소지가 있음을 알 수 있는 것이, 0666, 0777은 UNIX 파일 시스템에서만 유효한 권한(permission)이기 때문이다.
DOS의 파일 속성(읽기,쓰기,숨김,시스템,디렉토리)과 UNIX의 권한(소유자,그룹,관리자의 읽기,쓰기,실행 권리)를 서로 같은 것으로 간주해서 다루고 있다는 것이다.

그러면 정말로 이렇게 온동하여 처리한 것이 문제가 되는 것일까?
앞서 디버그 메시지에서는 perm이 0x20이었음을 확인했다.
8진수인 0777은 0x1FF, AND 연산을 한다해도 여전히 0x20이 되므로 결과적으로는 문제가 되지 않을 것으로 보인다.
그러면 뭘까?

mch_open()을 다시 확인해 보자.
mch_open()은 open()로 연결되어 있다.
mch_open() 매크로
open()의 help를 확인해 보자.
open()의 help
세번째 인자인 mode는 생략이 가능한 것으로 나와있다.
open()의 help (계속)
mode를 더 확인해 보니,
mode의 help
_chmod()의 file-attribute와는 다른 상수들이다.
실제 값은 어떨까?
sys/stat.h의 mode
이렇게 보니 _chmod()와 open()은 전혀 다른 계통의 함수들로 연계하여 사용하기에는 문제가 있어보인다.
open()은 기존의 UNIX 파일 시스템과의 호환성을 염두에 두고 MS-DOS에 포팅이 되었다고 한다면 _chmod()는 MS-DOS의 파일시스템에서만 사용할 수 있게 독자적으로 만들어진 것으로 보인다.


그렇다면, mch_open()의 세번째 인자의 값을 바꾸어주면 문제가 없을까?
하지만 정말 이 부분이 문제였다면, Windows에서 DOSBox를 구동하여 vim을 사용했을 때에도 동일한 문제가 발생해야 한다.
암튼 일단은 세번째 인자를 고쳐서 해 보기로 하자.

vim의 소스들을 살펴보니 대부분 세번째 인자로 0을 사용하고 있으며, 위의 stat.h에서도 일반적인 파일은 0을 사용한다고 되어 있기에 무조건 0을 사용하도록 수정해 보았다.
FILEIO.C
DOSBox에서 다시 make
make
그리고 기존의 파일을 열어서 수정하고 다시 저장해보니...
save
역시 예상과 같이 이것이 문제가 아니였던듯....

2014년 10월 18일 토요일

Vim 파일 저장 오류 __ 4

일단 터보 디버거는 미뤄두고, 간단히 메시지로 디버깅...

메시지 출력에 원하는 정보를 넣어서 출력하게 하려면 소스를 조금 수정해야 한다.

일단 메시지용 변수를 추가하고, 출력할 메시지를 만드는 부분을 추가해야 한다.

메시지 출력용 변수 추가 (#2781)

출력할 메시지 만들기 (#3970,#3971)

소스의 수정은 Ubuntu 상에서 했으므로, DOSBox에서는 파일이 변경된 것으로 인식할지 아닐지 몰라서 touch 한번 해주고 make를 해 보았다.
빌드 성공

우선 newfile 이라는 이름으로 새 파일을 만들어 본다.
새 파일 만들기

새 파일 만들기는 이전에 그랬듯이 성공.
저장 성공

이번에는 수정하기.
수정 실패, 메시지 확인.
역시나 실패. 메시지는 원했던 대로 출력되었다.
변수 값은 append = 0, forceit = 0, perm = 32

이 값들의 의미를 확인하기 위해 다시 소스를 보자.

append가 0인 것은 약간 의외....이지만 큰 영향은 아닌 듯 보임.
forceit은 당연히 0일 것이다.(":w!"가 아닌 ":w"였으니까..)
그런데 perm은 32? 8진수로 바꾸면 040?
UNIX 파일시스템이라면 소유자의 권한은 없고, 그룹은 쓰기 권한만 있는 셈?
하지만, 이건 MS-DOS의 FAT 파일시스템이므로 무슨 의미인지 정확하지가 않다.
그런데도 소스에서는 0666, 0777과 같이 UNIX 파일 시스템에서의 권한과 동일하게 다루고 있는 모습은 의문이다.

우선 perm의 값이 어떻게 32가 나온것인지 확인해 보기 위해 소스를 따라가 보자.
위의 mch_open() 이전에 perm 값을 구해 오는 부분은 다음의 mch_getperm() 부분이다.

perm을 구하는 부분
 mch_getperm()은 다시 vim_chmod()를 호출한다.
mch_getperm()
 vim_chmo()에서는 _chmod() 함수를 호출한다.
vim_chmod()
_chmod()는 UNIX의 chmod() 함수와는 다른 것으로 보인다.(인자의 갯수도 다름)

Borland C 매뉴얼을 찾아 봐야할 듯...

2014년 10월 17일 금요일

Vim 파일 저장 오류 __ 3

먼저 Vim의 소스를 직접 빌드하여 디버깅 해 보기로 결정.

vim의 소스는 다음 링크에서...
ftp://ftp.vim.org/pub/vim/pc

MS-DOS의 경우에는 vim 7.1이 최종 소스이므로 vim71src.zip을 다운로드 하면 된다.

소스를 풀어서 src 디렉토리를 살펴보면 INSTALLpc.txt라는 파일에 소스 빌드에 관한 안내가 되어 있다.

그 가운데 MS-DOS에 관한 부분.
INSTALLpc.txt
네모친 부분을 읽어 보면 Borland C++을 사용하는게 제일 속편할 듯...

그리고 부가적으로 spawno라는 라이브러리가 필요하다고 한다.
위에서는 simtel에서 다운로드 하라고 하는데, 이걸 만든 저자 Ralf Brown의 사이트를 본 적이 있어서 그곳에서 다운로드 받았다.

http://www.cs.cmu.edu/~ralf/files.html (예전에 MS-DOS 인터럽트를 정리해 둔 곳이라고 했던 URL. 이 페이지를 살펴보면 spawno 라이브러리를 찾을 수 있다.)
http://www.cs.cmu.edu/~ralf/pub-files/spwno413.zip (spawno 라이브러리)

project라는 서브 디렉토리 아래에 모두 풀어 놓았다.
디렉토리 모습
vim과 spawno 트리

소스를 빌드하기 위한 작업은,
1. 당연한 사항이지만 Borland C++을 설치해서 path 지정해 두기
2. src/Make_bc3.mak를 Makefile로 복사(또는 이름 바꾸기)
3. Makefile 수정하기
Makefile 수정
4. make

빌드는 성공적으로 완료.
디버깅을 위해 터보디버거를 이용해 구동.
하지만 ...메모리 부족 에러 발생ㅠㅠ
터보디버거 에러

고민하며 둘러보다 Makefile을 추가적으로 수정해야 함을 알게 됨.
주석에 씌어진 대로 80386 코드로 생성하도록 "-1-"을 "-3"으로, 소스 디버깅을 위해서 "-v" 옵션을 추가.
Makefile 추가 수정

하지만 결과는 마찬가지...

이제 해 볼 수 있는 방법은,
td386.exe라는 386용 터보디버거를 사용하는 방법과
소스에 메시지를 넣어서 메시지로 디버깅하는 방법.
전자는 터보디버거에 대한 매뉴얼을 좀 읽어 봐야 할 수 있을 것 같으니 후자를 먼저 해 보는 것이 좋을 듯...

Vim 파일 저장 오류 __ 2

문제의 에러코드를 이용해 소스 확인 fileio.c

오류 메시지의 해당 소스

mch_open()이라는 함수의 실패로 인한 오류 메시지였음.

mch_open()은 open() 함수

open()의 man page

open()의 man page, mode와 관련된 부분.

DosBox에서 Vim으로 새로운 파일을 만들어 본다.

내용을 입력하고 저장

정상적으로 저장이 되었음

Ubuntu의 file system에서 확인해 보면 파일의 권한이 644임을 알 수 있음

Vim에서는 수정이 안되지만, edit라는 다른 프로그램으로 수정을 함

정상적으로 수정이 되었음을 알 수 있다

어째서 vim 계열의 프로그램들만 파일의 수정에 문제가 생기는 것일까?
(vim외에도 elvis라는 프로그램도 문제가 발생한다.)
어째서 다른 에디터로는 문제가 없는 것일까?

이 문제의 원인을 어떻게 찾아낼 것인가?
MS-DOS 상에서 소스를 빌드하고 디버깅을 해야 할까?
DOSBox를 디버그 모드로 실행하고 MS-DOS Interrupt를 break point로 해서 확인을 해야 할까?

이 문제의 원인을 찾아내서 문제의 원인이 DOSBox인 경우, vim인 경우에 각각 어떻게 할 것인가?
아니다 이 문제는 DOSBox 뿐 아니라 Virtual Box의 경우에도 발생하므로 vim의 문제로 보는 것이 맞을 것이다.
단지, vim에서 FAT을 기준으로 작동하는 코드, 그리고 Linux상의 MS-DOS 에뮬레이터들이 FAT을 다루는 부분이 서로 충돌해서 빚어진 것이 아닐까 싶다.

2014년 10월 15일 수요일

Vim 파일 저장 오류 __ 1

[개요]
Ubuntu 10.04 운영체제에서 MS-DOS용 Vim을 사용하면 파일의 저장에 문제가 발생 함.

[사용 환경]
Ubuntu 10.04
DosBox 0.74 (혹은 Oracle Virtual Box에 MS-DOS를 설치한 경우)
Vim 7.1 for MS-DOS 16 bit version

[문제 현상1]
1. MS-DOS 에뮬레이터를 구동한다.
2. 이 에뮬레이터 상에 Vim 7.1 16 bit version이 설치되어 있고, path에 지정되어 있도록 한다.
3. 임의의 텍스트 파일이 존재하는 곳으로 이동하여, "vim <파일이름>"을 입력한다.
4. 파일을 수정한 후에, command mode로 전환하고 ':w'를 입력하여 저장을 해 본다.
!!! 파일이 저장되지 않고 다음과 같은 오류 문자열을 출력한다.
"<파일이름> E212: Can't open file for writing"


[문제 현상2]

1. MS-DOS 에뮬레이터를 구동한다.
2. 이 에뮬레이터 상에 Vim 7.1 16 bit version이 설치되어 있고, path에 지정되어 있도록 한다.
3. 임의의 디렉토리에서, "vim <새 파일 이름>"을 입력한다.
4. 내용을 입력한 후에, command mode로 전환하고 ':w'를 입력하여 저장을 해 본다.
5. 파일이 저장되고 다음과 같은 메시지가 출력된다.
"<새 파일 이름> [New] xxL, yyC written" (xx는 줄의 수, yy는 문자 수)
6. 이제 새로운 내용을 추가한 후에, command mode로 전환하고 ':w'를 입력하여 저장을 해 본다.
!!! 파일이 저장되지 않고 다음과 같은 오류 문자열을 출력한다.
"<파일이름> E212: Can't open file for writing"


2013년 12월 22일 일요일

Appler 디버깅하기 ___ 버그 발생

Appler 디버깅하기
라는 제목으로 게시했던 1번부터 6번까지의 게시물을 무효화 하겠음.

무효화 이유는,
수정된 Appler의 작동에 문제가 발생했기 때문.
Apple 게임인 2400AD를 실행하면, 초기 로고화면이 지나고 게임 화면의 프레임만 그려진 상태에서 Appler가 Halt 됨.

정상적으로 시작된 게임 화면

수정된 Appler는 이 화면에서 멈추어 버림

7번 게시물에서 제시한 방법대로 DOSBox를 수정한 버전에서는, 원래의 Appler로 문제없이 진행이 됨을 확인하였음.
하지만 1~6 게시물의 방법으로 수정된 Appler는 어떤 DOSBox에서도 문제가 있었기에, 수정된 Appler의 문제임은 확실함.


추정 원인은,
마지막 6번 게시물에서 만든 수정코드가 아니라,
1번과 2번 게시물에서 소스를 빌드하는 과정에 컴파일 오류를 수정하는 과정에서 발생한 것으로 생각 됨.
왜냐하면, 6번게시물에서 수정한 부분은 단지 Disk Manager 화면에만 영향을 줄 뿐 임.


확인 해 본 사항들
  • 1번과 2번 게시물에서 수정했던 부분에 대한 이해가 부족했기에, 이 부분을 제대로 고치기 위해서 어떻게 작동하는지 확인해 보아야겠다고 생각했음.
  • 이를 위해서, 수정한 부분이 실행파일에 어떤 식으로 컴파일되어 들어가 있는지 확인해야 하며, 원래의 실행파일에는 어떻게 컴파일되어 들어가 있는지 확인을 해야 했음.
  • 일단 수정한 실행 파일과 원래의 실행 파일을 비교하니 전자는 .EXE 파일이었고, 후자는 .COM 파일이었음.
  • 더욱이 시작 코드는 더욱 달라서 전자는 xor al, al이었고 후자는 mov ax, 4xxxH 였음.
  • 아무래도 바로 비교는 힘들었기에 EXE를 COM으로 바꿔보기 위해서 EXE2BIN을 사용해 보았음.
  • FreeDOS용 EXE2BIN은 모두 실패했음
  • MS-DOS 6.22용 EXE2BIN은 DOSBox에서 버전 불일치로 실행이 안 됨. DOSBox의 MS-DOS 버전은 5.0으로 되어 있음.
  • MS-DOS 5.0용 EXE2BIN은 Insufficient Memory라는 에러를 내며 실패했음.
  • Sourcer를 사용해 보았지만, 앞서와 비슷하게 (xor al,al, mov ax,...)차이가 나기에 모든 소스를 다 이해하기 전에는 원하는 부분이 어떻게 컴파일되어 들어가 있는지 찾아내기는 거의 불가능해 보임.
  • 심지어는 과연 Appler의 소스가 실행파일의 소스가 맞는지 의심되기도 함.
  • Appler의 소스는 Zophar's Domain에서만 받을 수 있었고, Appler의 공식 사이는 없기에 신뢰성이 떨어짐.
  • Appler의 소스에 있는 문서로는 터보어셈블러 2.x와 4.x로 빌드 되는 것을 확인했다고 했는데, 나는 터보 어셈블러 5.0으로 빌드하였던 것이기에 터보 어셈블러 2.0을 구해서 빌드해 보았으나 더 많은 에러가 발생함. 이 때문에 소스에 대한 신뢰성이 더 떨어지게 되었음.

이상의 실험 결과, 주어진 소스를 활용한다는 것 자체에 의문이 들어,
DOSBox를 수정하는 방법인 7번 게시물만을 유효한 것으로 인정하고
1번 ~ 6번 게시물은 무효화 하기로 결정했음.