나래온 툴 내부 구조 – 2. 경로가 지정된 객체들

필요성

나래온 툴에는 경로가 필요한 객체들이 많다. 대표적으로 물리 드라이브 그 자체인 TPhysicalDrive부터, 수많은 Getter 객체들이 모두 해당 드라이브의 경로를 필요로 한다. 이외에도 파티션을 지정하는 객체의 경우에도 경로를 필요로 한다. 이 경우 각 행동을 수행할 때마다 경로를 기입하게 하는 것은 부자연스러울 뿐더러 혼동의 가능성이 매우 크다. 따라서 객체가 생성될 때 경로를 지정하고 내부에서 경로를 보관하게 하는 식으로 설계하였다.

따라서 본편의 내용은 자칫 불필요하게 보일 수 있지만, 본편의 내용은 프로젝트 전체에 걸쳐 반복되므로 필수적으로 이해가 필요하다.

생각보다 내용이 길어져 두 편으로 분리하게 되었다. PhysicalDrive 관련한 내용은 다음 편에 나올 예정이다.

기본형: TOSFile

가장 기본적인 형태는 TOSFile이다. (어떤 경로던 확인하지 않고) 경로를 저장하며, OS 에러 코드를 exception으로 바꾸는 기능을 탑재하고 있다. GetLastError를 체크해서 매번 에러 처리를 하는 일은 매우 복잡해 잊기 쉽다. 하지만 이 구조에서는 IfOSErrorRaiseException 함수를 부르는 것으로 간단하게 이 문제를 해결할 수 있다. 해당 부분의 소스는 다음과 같다.

[snippet slug=ifoserrorraiseexception lang=pascal]

또한 내부에서 빈번하게 이뤄지는 요청 중 하나가 접두어를 분리하는 문제다. 예를 들어, \\.\PhysicalDrive7에서 7을 뽑아내는 일, \\.\C:에서 C:를 뽑아내는 일이다. 이 부분을 GetPathOfFileAccessingWithoutPrefix 함수로 구현하였다.

[snippet slug=getpathoffileaccessingwithoutprefix lang=pascal]

윈도우 경로는 대소문자를 구별하지 않기 때문에, 내부에서는 대문자로 통일된다. 문자열 비교도 따로 IsPathEqual 함수를 제공하여 오류가 없게 했다.

[snippet slug=uppercase lang=pascal]

핸들이 필요할 때: TOSFileWithHandle

경로를 직접 사용해 API를 호출할 때가 아니라, 핸들이 필요할 때가 있다. 이런 때 사용하는 것이 TOSFileWithHandle 객체다. 이 클래스 내부의 GetMinimumPrivilege 함수를 override하여 핸들들이 각 상황에 알맞는 권한(읽기, 쓰기 권한)만을 가지게 된다. 또한 설정이 매우 복잡한 Security descriptor를 생성하는 과정 또한 통합해 핸들의 보안성을 높였다.

[snippet slug=createhandle lang=pascal]

대부분의 작업들은 TFileHandle 내부에서 이루어지는데, 여기에 있는 Unlock 함수는 좀 특별하다. 이 함수는 이동식 저장장치면서 SAT 장치인 스토리지(Z80)에 초기화 ISO 기록 등을 위해 직접 접근해야 할 때, 프로그램에 남아있던 모든 핸들을 해제하기 위해서 사용된다. 해당 작업이 완료되는 즉시 핸들을 새로 만들어야 하므로, 상태 자체가 IOSFileUnlock 인터페이스로 관리된다.

[snippet slug=tosfileunlock lang=pascal]

ioctl이 필요할 때: TIoControlFile

ioctl은 그 자체로 프로그램 내에서 상당히 빈번히 쓰이는 패턴이다. 따라서 별도의 객체로 분리해버리고, ioctl code를 따로 분리하게 만들었다. 하지만 가장 큰 의의는 메타클래스를 통해 ioctl에 들어갈 구조체의 형을 명확하게 지정할 수 있다는 점이다. 또한 그를 통해 버퍼 사이즈 지정 부분에 오류가 없게 된다. 이는 반복적인 패턴에서 빈번하게 발생하는 오류라서 연구를 통해 집어넣게 되었다.

[snippet slug=buildosbufferby lang=pascal]

요약

나래온 툴의 객체들은 경로를 필요로 하고, 반복되는 부분을 다음과 같은 클래스로 만들었다.

  1. TOSFile: Path
  2. TOSFileWithHandle: Path + Handle
  3. TIoControlFile: Path + Handle + Ioctl