SFUSE_Documentation
로딩중...
검색중...
일치하는것 없음
fs.h 파일 참조
#include "super.h"
#include <fuse3/fuse.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
fs.h에 대한 include 의존 그래프
이 그래프는 이 파일을 직/간접적으로 include 하는 파일들을 보여줍니다.:

이 파일의 소스 코드 페이지로 가기

데이터 구조

struct  sfuse_fs
 SFUSE 파일 시스템 컨텍스트 구조체 더 자세히 ...

함수

struct sfuse_fsfs_initialize (const char *path, int *error_out)
 파일 시스템 초기화
void fs_teardown (struct sfuse_fs *fs)
 파일 시스템 정리
int fs_resolve_path (struct sfuse_fs *fs, const char *path, uint32_t *out_ino)
 경로를 inode 번호로 변환
int fs_getattr (struct sfuse_fs *fs, const char *path, struct stat *stbuf)
 파일/디렉터리 속성 조회
int fs_access (struct sfuse_fs *fs, const char *path, int mask)
 접근 권한 검사
int fs_readdir (struct sfuse_fs *fs, const char *path, void *buf, fuse_fill_dir_t filler, off_t offset)
 디렉터리 내용 읽기
int fs_open (struct sfuse_fs *fs, const char *path, struct fuse_file_info *fi)
 파일 열기
int fs_read (struct sfuse_fs *fs, const char *path, char *buf, size_t size, off_t offset)
 파일 읽기
int fs_write (struct sfuse_fs *fs, const char *path, const char *buf, size_t size, off_t offset)
 파일 쓰기
int fs_create (struct sfuse_fs *fs, const char *path, mode_t mode, struct fuse_file_info *fi)
 파일 생성
int fs_mkdir (struct sfuse_fs *fs, const char *path, mode_t mode)
 디렉터리 생성
int fs_unlink (struct sfuse_fs *fs, const char *path)
 파일 삭제
int fs_rmdir (struct sfuse_fs *fs, const char *path)
 디렉터리 삭제
int fs_rename (struct sfuse_fs *fs, const char *from, const char *to)
 파일 또는 디렉터리 이름 변경
int fs_truncate (struct sfuse_fs *fs, const char *path, off_t size)
 파일 크기 조정 (truncate)
int fs_utimens (struct sfuse_fs *fs, const char *path, const struct timespec tv[2])
 파일의 시간 속성 변경 (utimens)
int fs_flush (struct sfuse_fs *fs, const char *path, struct fuse_file_info *fi)
 FUSE에서 플러시 요청 처리
int fs_fsync (struct sfuse_fs *fs, const char *path, int datasync, struct fuse_file_info *fi)
 FUSE에서 fsync 요청 처리
struct fuse_operations * sfuse_get_operations (void)
 SFUSE용 FUSE operations 구조체 반환

변수

bool g_force_format = false
 강제 포맷 옵션 플래그

함수 문서화

◆ fs_access()

int fs_access ( struct sfuse_fs * fs,
const char * path,
int mask )

접근 권한 검사

매개변수
fs파일 시스템 컨텍스트
path대상 경로
mask검사할 접근 마스크
반환값
성공 시 0, 실패 시 음수 오류 코드

접근 권한 검사

매개변수
fs파일 시스템 컨텍스트 포인터
path검사할 경로 (null-terminated 문자열)
mask접근 마스크 (R_OK, W_OK, X_OK)
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 1343 번째 라인에서 정의되었습니다.

1343 {
1344 uint32_t ino;
1345 /* 경로 → inode 변환 실패 시 ENOENT 반환 */
1346 if (fs_resolve_path(fs, path, &ino) < 0)
1347 return -ENOENT;
1348 /* mask에 따른 실제 권한 검사는 필요 시 구현 가능 */
1349 (void)mask;
1350 return 0;
1351}
int fs_resolve_path(struct sfuse_fs *fs, const char *path, uint32_t *out_ino)
경로 문자열을 inode 번호로 변환
Definition fs.c:198
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_create()

int fs_create ( struct sfuse_fs * fs,
const char * path,
mode_t mode,
struct fuse_file_info * fi )

파일 생성

매개변수
fs파일 시스템 컨텍스트
path생성할 파일 경로
mode생성 모드 (퍼미션)
fiFUSE 파일 정보 구조체
반환값
성공 시 0, 실패 시 음수 오류 코드

파일 생성

지정된 경로에 새 파일을 생성하고 상위 디렉터리에 디렉터리 엔트리를 추가한다.

매개변수
fs파일 시스템 컨텍스트 포인터
path생성할 파일 경로 (null-terminated 문자열)
mode파일 모드 및 권한 (하위 12비트 사용)
fiFUSE 파일 정보 구조체 (사용되지 않음)
반환값
성공 시 0, 실패 시 음수 오류 코드

< 일반 파일로 설정

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

fs.c 파일의 570 번째 라인에서 정의되었습니다.

571 {
572 (void)fi;
573
574 uint32_t dummy;
575 /* 이미 존재하면 실패 */
576 if (fs_resolve_path(fs, path, &dummy) == 0) {
577 return -EEXIST;
578 }
579
580 /* 상위 디렉터리와 새 파일 이름 분리 */
581 char *path_copy = strdup(path);
582 if (!path_copy)
583 return -ENOMEM;
584 char *name = strrchr(path_copy, '/');
585 if (!name || *(name + 1) == '\0') {
586 free(path_copy);
587 return -EINVAL;
588 }
589 *name = '\0';
590 char *parent_path = (*path_copy == '\0') ? "/" : path_copy;
591 name++;
592
593 /* 상위 디렉터리 inode 찾기 */
594 uint32_t parent_ino;
595 if (fs_resolve_path(fs, parent_path, &parent_ino) < 0) {
596 free(path_copy);
597 return -ENOENT;
598 }
599
600 struct sfuse_inode parent_inode;
601 inode_load(fs->backing_fd, &fs->sb, parent_ino, &parent_inode);
602 /* 상위가 디렉터리인지 확인 */
603 if ((parent_inode.mode & S_IFDIR) == 0) {
604 free(path_copy);
605 return -ENOTDIR;
606 }
607
608 /* 새 아이노드 할당 */
609 int new_ino = alloc_inode(&fs->sb, &fs->bmaps->inode);
610 if (new_ino < 0) {
611 free(path_copy);
612 return new_ino;
613 }
614
615 /* 새 아이노드 초기화 */
616 struct sfuse_inode new_inode;
617 memset(&new_inode, 0, sizeof(new_inode));
618 new_inode.mode = (mode & 0xFFF) | S_IFREG;
619 new_inode.uid = getuid();
620 new_inode.gid = getgid();
621 new_inode.size = 0;
622 time_t now = time(NULL);
623 new_inode.atime = (uint32_t)now;
624 new_inode.mtime = (uint32_t)now;
625 new_inode.ctime = (uint32_t)now;
626
627 /* 상위 디렉터리에 엔트리 추가 */
628 uint8_t dir_block[SFUSE_BLOCK_SIZE];
629 bool added = false;
630 for (int i = 0; i < 12 && !added; ++i) {
631 if (parent_inode.direct[i] == 0) {
632 /* 새 디렉터리 블록 할당 및 초기화 */
633 int new_dir_block = alloc_block(&fs->sb, &fs->bmaps->block);
634 if (new_dir_block < 0) {
635 free_inode(&fs->sb, &fs->bmaps->inode, new_ino);
636 free(path_copy);
637 return -ENOSPC;
638 }
639 parent_inode.direct[i] =
640 fs->sb.data_block_start + (uint32_t)new_dir_block;
641
642 memset(dir_block, 0, SFUSE_BLOCK_SIZE);
643 struct sfuse_dirent *entries = (struct sfuse_dirent *)dir_block;
644 entries[0].inode = new_ino;
645 strncpy(entries[0].name, name, SFUSE_NAME_MAX - 1);
646 entries[0].name[SFUSE_NAME_MAX - 1] = '\0';
647
648 write_block(fs->backing_fd, parent_inode.direct[i], dir_block);
649 parent_inode.size += SFUSE_BLOCK_SIZE;
650 added = true;
651 } else {
652 /* 기존 블록에서 빈 슬롯 검색 */
653 if (read_block(fs->backing_fd, parent_inode.direct[i], dir_block) < 0) {
654 free_inode(&fs->sb, &fs->bmaps->inode, new_ino);
655 free(path_copy);
656 return -EIO;
657 }
658 struct sfuse_dirent *entries = (struct sfuse_dirent *)dir_block;
659 for (uint32_t j = 0; j < DENTS_PER_BLOCK; ++j) {
660 if (entries[j].inode == 0) {
661 entries[j].inode = new_ino;
662 strncpy(entries[j].name, name, SFUSE_NAME_MAX - 1);
663 entries[j].name[SFUSE_NAME_MAX - 1] = '\0';
664 write_block(fs->backing_fd, parent_inode.direct[i], dir_block);
665 added = true;
666 break;
667 }
668 }
669 }
670 }
671
672 if (!added) {
673 /* 공간 부족 시 롤백 */
674 free_inode(&fs->sb, &fs->bmaps->inode, new_ino);
675 free(path_copy);
676 return -ENOSPC;
677 }
678
679 /* 새 아이노드를 디스크에 기록 */
680 inode_sync(fs->backing_fd, &fs->sb, new_ino, &new_inode);
681
682 /* 상위 디렉터리 메타데이터 갱신 */
683 parent_inode.mtime = (uint32_t)now;
684 parent_inode.ctime = (uint32_t)now;
685 inode_sync(fs->backing_fd, &fs->sb, parent_ino, &parent_inode);
686
687 free(path_copy);
688 return 0;
689}
int alloc_inode(struct sfuse_superblock *sb, struct sfuse_inode_bitmap *imap)
슈퍼블록 기반으로 아이노드 할당
Definition bitmap.c:95
void free_inode(struct sfuse_superblock *sb, struct sfuse_inode_bitmap *imap, uint32_t ino)
슈퍼블록 기반으로 아이노드 해제
Definition bitmap.c:109
int alloc_block(struct sfuse_superblock *sb, struct sfuse_block_bitmap *bmap)
슈퍼블록 기반으로 데이터 블록 할당
Definition bitmap.c:121
ssize_t read_block(int fd, uint32_t blk, void *out_buf)
지정한 블록 번호의 데이터를 읽어 버퍼에 저장
Definition block.c:15
ssize_t write_block(int fd, uint32_t blk, const void *buf)
버퍼의 내용을 지정한 블록 번호에 기록
Definition block.c:31
#define SFUSE_NAME_MAX
Definition dir.h:10
#define DENTS_PER_BLOCK
한 블록당 디렉터리 엔트리 수
Definition dir.h:14
int inode_load(int fd, const struct sfuse_superblock *sb, uint32_t ino, struct sfuse_inode *out)
디스크 이미지에서 아이노드를 읽어 구조체에 로드
Definition inode.c:32
int inode_sync(int fd, const struct sfuse_superblock *sb, uint32_t ino, const struct sfuse_inode *in)
아이노드 구조체 내용을 디스크 이미지에 동기화
Definition inode.c:51
struct sfuse_block_bitmap block
Definition bitmap.h:32
struct sfuse_inode_bitmap inode
Definition bitmap.h:31
디스크에 저장되는 디렉터리 엔트리 구조체
Definition dir.h:19
uint32_t inode
Definition dir.h:20
char name[256]
Definition dir.h:21
struct sfuse_bitmaps * bmaps
Definition fs.h:24
struct sfuse_superblock sb
Definition fs.h:23
int backing_fd
Definition fs.h:22
디스크에 저장되는 아이노드 구조체
Definition inode.h:22
uint32_t mode
Definition inode.h:23
uint32_t data_block_start
Definition super.h:60
#define SFUSE_BLOCK_SIZE
블록 크기 (바이트 단위)
Definition super.h:20
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_flush()

int fs_flush ( struct sfuse_fs * fs,
const char * path,
struct fuse_file_info * fi )

FUSE에서 플러시 요청 처리

매개변수
fs파일 시스템 컨텍스트
path대상 파일 경로
fiFUSE 파일 정보 구조체
반환값
성공 시 0, 실패 시 음수 오류 코드

FUSE에서 플러시 요청 처리

매개변수
fs파일 시스템 컨텍스트 포인터
path대상 경로 (사용되지 않음)
fiFUSE 파일 정보 구조체 (사용되지 않음)
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 1302 번째 라인에서 정의되었습니다.

1302 {
1303 (void)path;
1304 (void)fi;
1305 if (fsync(fs->backing_fd) < 0)
1306 return -errno;
1307 return 0;
1308}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_fsync()

int fs_fsync ( struct sfuse_fs * fs,
const char * path,
int datasync,
struct fuse_file_info * fi )

FUSE에서 fsync 요청 처리

매개변수
fs파일 시스템 컨텍스트
path대상 파일 경로
datasync데이터 sync 플래그
fiFUSE 파일 정보 구조체
반환값
성공 시 0, 실패 시 음수 오류 코드

FUSE에서 fsync 요청 처리

매개변수
fs파일 시스템 컨텍스트 포인터
path대상 경로 (사용되지 않음)
datasync데이터만 동기화할지 여부
fiFUSE 파일 정보 구조체 (사용되지 않음)
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 1280 번째 라인에서 정의되었습니다.

1281 {
1282 (void)path;
1283 (void)fi;
1284 if (datasync) {
1285 if (fdatasync(fs->backing_fd) < 0)
1286 return -errno;
1287 } else {
1288 if (fsync(fs->backing_fd) < 0)
1289 return -errno;
1290 }
1291 return 0;
1292}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_getattr()

int fs_getattr ( struct sfuse_fs * fs,
const char * path,
struct stat * stbuf )

파일/디렉터리 속성 조회

매개변수
fs파일 시스템 컨텍스트
path대상 경로
stbuf출력할 stat 구조체 포인터
반환값
성공 시 0, 실패 시 음수 오류 코드

파일/디렉터리 속성 조회

지정 경로의 inode를 조회하여 stat 구조체에 채움

매개변수
fs파일 시스템 컨텍스트 포인터
path대상 경로 문자열
stbuf속성 정보를 채울 stat 구조체 포인터
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 237 번째 라인에서 정의되었습니다.

237 {
238 uint32_t ino;
239 int ret = fs_resolve_path(fs, path, &ino);
240 if (ret < 0)
241 return ret;
242
243 struct sfuse_inode inode;
244 if (inode_load(fs->backing_fd, &fs->sb, ino, &inode) < 0)
245 return -EIO;
246
247 /* stat 구조체 초기화 및 채우기 */
248 memset(stbuf, 0, sizeof(*stbuf));
249 stbuf->st_mode = inode.mode;
250 stbuf->st_nlink = S_ISDIR(inode.mode) ? 2 : 1;
251 stbuf->st_uid = inode.uid;
252 stbuf->st_gid = inode.gid;
253 stbuf->st_size = inode.size;
254 stbuf->st_atime = inode.atime;
255 stbuf->st_mtime = inode.mtime;
256 stbuf->st_ctime = inode.ctime;
257 return 0;
258}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_initialize()

struct sfuse_fs * fs_initialize ( const char * path,
int * error_out )

파일 시스템 초기화

매개변수
image_path디스크 이미지 파일 경로
error_out오류 코드를 저장할 포인터
반환값
초기화된 sfuse_fs 포인터 또는 NULL

파일 시스템 초기화

  • 블록 디바이스 여부를 if (ioctl(fd, BLKGETSIZE64, &size64) < 0) {검사해, 블록 디바이스는 ioctl(BLKGETSIZE64)로 크기 취득
  • 일반 파일(이미지)인 경우만 lseek/SEEK_END와 ftruncate 사용

fs.c 파일의 105 번째 라인에서 정의되었습니다.

105 {
106 int fd = open(path, O_RDWR);
107 if (fd < 0) {
108 *error_out = errno;
109 return NULL;
110 }
111
112 struct stat st;
113 if (fstat(fd, &st) < 0) {
114 *error_out = errno;
115 close(fd);
116 return NULL;
117 }
118
119 off_t img_size;
120 bool is_blkdev = S_ISBLK(st.st_mode);
121 if (is_blkdev) {
122 // 블록 디바이스: ioctl로 전체 크기(바이트) 가져오기
123 uint64_t size64;
124 if (ioctl(fd, BLKGETSIZE64, &size64) < 0) {
125 *error_out = errno;
126 close(fd);
127 return NULL;
128 }
129 img_size = size64;
130 } else {
131 // 일반 파일: lseek로 크기 측정
132 img_size = lseek(fd, 0, SEEK_END);
133 if (img_size < 0) {
134 *error_out = errno;
135 close(fd);
136 return NULL;
137 }
138 }
139
140 // 강제 포맷 시 이미지 파일만 ftruncate — 블록 디바이스는 넘어감
141 if (g_force_format && !is_blkdev) {
142 if (ftruncate(fd, img_size) < 0) {
143 *error_out = errno;
144 close(fd);
145 return NULL;
146 }
147 }
148
149 // 다음 I/O를 위해 파일 포인터를 맨 앞으로
150 if (lseek(fd, 0, SEEK_SET) < 0) {
151 *error_out = errno;
152 close(fd);
153 return NULL;
154 }
155}
bool g_force_format
강제 포맷 옵션 플래그
Definition main.c:32
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_mkdir()

int fs_mkdir ( struct sfuse_fs * fs,
const char * path,
mode_t mode )

디렉터리 생성

매개변수
fs파일 시스템 컨텍스트
path생성할 디렉터리 경로
mode생성 모드 (퍼미션)
반환값
성공 시 0, 실패 시 음수 오류 코드

디렉터리 생성

지정된 경로에 새 디렉터리를 생성하고 상위 디렉터리에 디렉터리 엔트리를 추가한다.

매개변수
fs파일 시스템 컨텍스트 포인터
path생성할 디렉터리 경로 (null-terminated 문자열)
mode디렉터리 모드 및 권한 (하위 12비트 사용)
반환값
성공 시 0, 실패 시 음수 오류 코드

< 디렉터리 타입 설정

< 첫 엔트리에 새 inode 설정

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

< 디렉터리 크기 갱신

< 빈 슬롯에 inode 설정

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

< 수정 시간 갱신

< 변경 시간 갱신

fs.c 파일의 702 번째 라인에서 정의되었습니다.

702 {
703 uint32_t dummy;
704 /* 이미 존재하면 실패 */
705 if (fs_resolve_path(fs, path, &dummy) == 0) {
706 return -EEXIST;
707 }
708
709 /* 상위 디렉터리와 새 이름 분리 */
710 char *path_copy = strdup(path);
711 if (!path_copy)
712 return -ENOMEM;
713 char *name = strrchr(path_copy, '/');
714 if (!name || *(name + 1) == '\0') {
715 free(path_copy);
716 return -EINVAL;
717 }
718 *name = '\0';
719 char *parent_path = (*path_copy == '\0') ? "/" : path_copy;
720 name++;
721
722 /* 상위 디렉터리 inode 조회 */
723 uint32_t parent_ino;
724 if (fs_resolve_path(fs, parent_path, &parent_ino) < 0) {
725 free(path_copy);
726 return -ENOENT;
727 }
728
729 struct sfuse_inode parent_inode;
730 inode_load(fs->backing_fd, &fs->sb, parent_ino, &parent_inode);
731 /* 상위가 디렉터리가 아니면 오류 */
732 if ((parent_inode.mode & S_IFDIR) == 0) {
733 free(path_copy);
734 return -ENOTDIR;
735 }
736
737 /* 새 아이노드 할당 */
738 int new_ino = alloc_inode(&fs->sb, &fs->bmaps->inode);
739 if (new_ino < 0) {
740 free(path_copy);
741 return new_ino;
742 }
743
744 /* 새 아이노드 초기화 */
745 struct sfuse_inode new_inode;
746 memset(&new_inode, 0, sizeof(new_inode));
747 new_inode.mode = (mode & 0xFFF) | S_IFDIR;
748 new_inode.uid = getuid();
749 new_inode.gid = getgid();
750 new_inode.size = 0;
751 time_t now = time(NULL);
752 new_inode.atime = (uint32_t)now;
753 new_inode.mtime = (uint32_t)now;
754 new_inode.ctime = (uint32_t)now;
755
756 /* 상위 디렉터리에 엔트리 추가 (메모리 안전성: 블록 전체 초기화) */
757 uint8_t dir_block[SFUSE_BLOCK_SIZE];
758 bool added = false;
759 for (int i = 0; i < 12 && !added; ++i) {
760 if (parent_inode.direct[i] == 0) {
761 /* 새 디렉터리 블록 할당 */
762 int new_dir_block = alloc_block(&fs->sb, &fs->bmaps->block);
763 if (new_dir_block < 0) {
764 free_inode(&fs->sb, &fs->bmaps->inode, new_ino);
765 free(path_copy);
766 return -ENOSPC;
767 }
768 parent_inode.direct[i] =
769 fs->sb.data_block_start + (uint32_t)new_dir_block;
770
771 memset(dir_block, 0, SFUSE_BLOCK_SIZE);
772 struct sfuse_dirent *entries = (struct sfuse_dirent *)dir_block;
773 entries[0].inode = new_ino;
774 strncpy(entries[0].name, name, SFUSE_NAME_MAX - 1);
775 entries[0].name[SFUSE_NAME_MAX - 1] = '\0';
776
777 write_block(fs->backing_fd, parent_inode.direct[i], dir_block);
778 parent_inode.size += SFUSE_BLOCK_SIZE;
779 added = true;
780 } else {
781 /* 기존 블록에서 빈 슬롯 검색 */
782 if (read_block(fs->backing_fd, parent_inode.direct[i], dir_block) < 0) {
783 free_inode(&fs->sb, &fs->bmaps->inode, new_ino);
784 free(path_copy);
785 return -EIO;
786 }
787 struct sfuse_dirent *entries = (struct sfuse_dirent *)dir_block;
788 for (uint32_t j = 0; j < DENTS_PER_BLOCK; ++j) {
789 if (entries[j].inode == 0) {
790 entries[j].inode = new_ino;
791 strncpy(entries[j].name, name, SFUSE_NAME_MAX - 1);
792 entries[j].name[SFUSE_NAME_MAX - 1] = '\0';
793 write_block(fs->backing_fd, parent_inode.direct[i], dir_block);
794 added = true;
795 break;
796 }
797 }
798 }
799 }
800
801 /* 공간 부족 시 롤백 */
802 if (!added) {
803 free_inode(&fs->sb, &fs->bmaps->inode, new_ino);
804 free(path_copy);
805 return -ENOSPC;
806 }
807
808 /* 새 아이노드 디스크에 기록 */
809 inode_sync(fs->backing_fd, &fs->sb, new_ino, &new_inode);
810
811 /* 상위 디렉터리 메타데이터 갱신 */
812 parent_inode.mtime = (uint32_t)now;
813 parent_inode.ctime = (uint32_t)now;
814 inode_sync(fs->backing_fd, &fs->sb, parent_ino, &parent_inode);
815
816 free(path_copy);
817 return 0;
818}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_open()

int fs_open ( struct sfuse_fs * fs,
const char * path,
struct fuse_file_info * fi )

파일 열기

매개변수
fs파일 시스템 컨텍스트
path파일 경로
fiFUSE 파일 정보 구조체
반환값
성공 시 0, 실패 시 음수 오류 코드

파일 열기

path가 유효한 파일인지 확인

매개변수
fs파일 시스템 컨텍스트 포인터
path열고자 하는 파일 경로 문자열
fiFUSE 파일 정보 구조체 (사용하지 않음)
반환값
성공 시 0, 실패 시 -ENOENT

fs.c 파일의 290 번째 라인에서 정의되었습니다.

290 {
291 (void)fi;
292 uint32_t ino;
293 if (fs_resolve_path(fs, path, &ino) < 0)
294 return -ENOENT;
295 return 0;
296}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_read()

int fs_read ( struct sfuse_fs * fs,
const char * path,
char * buf,
size_t size,
off_t offset )

파일 읽기

매개변수
fs파일 시스템 컨텍스트
path파일 경로
buf읽은 데이터를 저장할 버퍼
size읽을 바이트 수
offset읽기 오프셋
반환값
읽은 바이트 수 또는 음수 오류 코드

지정된 경로의 파일 데이터를 읽어 사용자 버퍼에 복사한다.

매개변수
fs파일 시스템 컨텍스트 포인터
path읽을 파일 경로 (null-terminated 문자열)
buf데이터를 저장할 사용자 버퍼 포인터
size요청한 읽기 크기 (바이트 단위)
offset파일 내 시작 오프셋 (바이트 단위)
반환값
읽은 바이트 수 (>=0), 실패 시 음수 오류 코드

< 논리 블록 인덱스

< 블록 내 오프셋

< 이터레이션당 최대 읽기 바이트

fs.c 파일의 310 번째 라인에서 정의되었습니다.

311 {
312 uint32_t ino;
313 if (fs_resolve_path(fs, path, &ino) < 0)
314 return -ENOENT;
315
316 struct sfuse_inode inode;
317 if (inode_load(fs->backing_fd, &fs->sb, ino, &inode) < 0)
318 return -EIO;
319
320 /* 디렉터리는 읽을 수 없음 */
321 if ((inode.mode & S_IFDIR) == S_IFDIR)
322 return -EISDIR;
323
324 /* 오프셋이 파일 크기를 넘으면 0 리턴 */
325 if ((size_t)offset >= inode.size)
326 return 0;
327
328 /* 요청 크기가 파일 끝을 넘으면 조정 */
329 if ((size_t)offset + size > inode.size)
330 size = inode.size - offset;
331
332 size_t bytes_read = 0;
333 uint8_t block_buf[SFUSE_BLOCK_SIZE];
334
335 /* 필요한 블록을 반복해서 읽음 */
336 while (bytes_read < size) {
337 uint32_t block_index =
338 (offset + bytes_read) / SFUSE_BLOCK_SIZE;
339 uint32_t block_offset =
340 (offset + bytes_read) % SFUSE_BLOCK_SIZE;
341 uint32_t to_read =
342 SFUSE_BLOCK_SIZE - block_offset;
343
344 if (to_read > size - bytes_read)
345 to_read = size - bytes_read;
346
347 uint32_t disk_block = 0;
348
349 /* 직접 블록 참조 */
350 if (block_index < 12U) {
351 disk_block = inode.direct[block_index];
352 }
353 /* 단일 간접 블록 참조 */
354 else if (block_index < 12U + SFUSE_PTRS_PER_BLOCK) {
355 if (!inode.indirect)
356 break;
357 uint32_t ptrs[SFUSE_PTRS_PER_BLOCK];
358 if (read_block(fs->backing_fd, inode.indirect, ptrs) < 0)
359 return -EIO;
360 disk_block = ptrs[block_index - 12U];
361 }
362 /* 이중 간접 블록 참조 */
363 else {
364 if (!inode.double_indirect)
365 break;
366 uint32_t l1[SFUSE_PTRS_PER_BLOCK];
367 if (read_block(fs->backing_fd, inode.double_indirect, l1) < 0)
368 return -EIO;
369 uint32_t dbl_index = block_index - (12U + SFUSE_PTRS_PER_BLOCK);
370 uint32_t l1_idx = dbl_index / SFUSE_PTRS_PER_BLOCK;
371 uint32_t l2_idx = dbl_index % SFUSE_PTRS_PER_BLOCK;
372 if (l1_idx >= SFUSE_PTRS_PER_BLOCK || l1[l1_idx] == 0)
373 break;
374 uint32_t l2[SFUSE_PTRS_PER_BLOCK];
375 if (read_block(fs->backing_fd, l1[l1_idx], l2) < 0)
376 return -EIO;
377 disk_block = l2[l2_idx];
378 }
379
380 /* 할당되지 않은 블록이면 0으로 채움 */
381 if (disk_block == 0) {
382 memset(buf + bytes_read, 0, to_read);
383 } else {
384 /* 실제 디스크 읽기 */
385 if (read_block(fs->backing_fd, disk_block, block_buf) < 0)
386 return -EIO;
387 memcpy(buf + bytes_read, block_buf + block_offset, to_read);
388 }
389 bytes_read += to_read;
390 }
391
392 return bytes_read;
393}
#define SFUSE_PTRS_PER_BLOCK
한 블록에 담을 수 있는 포인터 수 (32-bit)
Definition inode.h:17
uint32_t size
Definition inode.h:26
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_readdir()

int fs_readdir ( struct sfuse_fs * fs,
const char * path,
void * buf,
fuse_fill_dir_t filler,
off_t offset )

디렉터리 내용 읽기

매개변수
fs파일 시스템 컨텍스트
path디렉터리 경로
bufFUSE가 제공하는 버퍼
filler디렉터리 엔트리 추가 콜백
offset읽기 오프셋
반환값
성공 시 0, 실패 시 음수 오류 코드

디렉터리 내용 읽기

지정 경로의 디렉터리 엔트리를 FUSE callback에 전달

매개변수
fs파일 시스템 컨텍스트 포인터
path디렉터리 경로 문자열
bufFUSE가 제공하는 버퍼 포인터
fillerFUSE 디렉터리 엔트리 추가 콜백
offset읽기 시작 오프셋 (사용되지 않음)
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 272 번째 라인에서 정의되었습니다.

273 {
274 uint32_t ino;
275 if (fs_resolve_path(fs, path, &ino) < 0)
276 return -ENOENT;
277 return dir_list(fs, ino, buf, filler, offset);
278}
int dir_list(const struct sfuse_fs *fs, uint32_t dir_ino, void *buf, fuse_fill_dir_t filler, off_t offset)
FUSE용 디렉터리 목록 채우기 콜백 호출
Definition dir.c:58
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_rename()

int fs_rename ( struct sfuse_fs * fs,
const char * from,
const char * to )

파일 또는 디렉터리 이름 변경

매개변수
fs파일 시스템 컨텍스트
from원본 경로
to대상 경로
반환값
성공 시 0, 실패 시 음수 오류 코드

파일 또는 디렉터리 이름 변경

지정된 경로의 엔트리를 원본 디렉터리에서 제거하고, 대상 디렉터리에 새 엔트리를 추가한다.

매개변수
fs파일 시스템 컨텍스트 포인터
from원본 경로 (null-terminated 문자열)
to대상 경로 (null-terminated 문자열)
반환값
성공 시 0, 실패 시 음수 오류 코드

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

< 파일/디렉터리 이름의 최대 길이

fs.c 파일의 1011 번째 라인에서 정의되었습니다.

1011 {
1012 uint32_t src_ino;
1013 if (fs_resolve_path(fs, from, &src_ino) < 0) {
1014 return -ENOENT;
1015 }
1016 uint32_t dummy;
1017 /* 대상이 이미 존재하면 실패 */
1018 if (fs_resolve_path(fs, to, &dummy) == 0) {
1019 return -EEXIST;
1020 }
1021
1022 /* 경로 복사 및 분할 */
1023 char *from_copy = strdup(from);
1024 char *to_copy = strdup(to);
1025 if (!from_copy || !to_copy) {
1026 free(from_copy);
1027 free(to_copy);
1028 return -ENOMEM;
1029 }
1030 char *from_name = strrchr(from_copy, '/');
1031 char *to_name = strrchr(to_copy, '/');
1032 *from_name = '\0';
1033 *to_name = '\0';
1034 char *from_parent_path = (*from_copy == '\0') ? "/" : from_copy;
1035 char *to_parent_path = (*to_copy == '\0') ? "/" : to_copy;
1036 from_name++;
1037 to_name++;
1038
1039 /* 부모 디렉터리 inode 조회 */
1040 uint32_t from_parent_ino, to_parent_ino;
1041 fs_resolve_path(fs, from_parent_path, &from_parent_ino);
1042 if (fs_resolve_path(fs, to_parent_path, &to_parent_ino) < 0) {
1043 free(from_copy);
1044 free(to_copy);
1045 return -ENOENT;
1046 }
1047
1048 struct sfuse_inode from_parent_inode, to_parent_inode;
1049 inode_load(fs->backing_fd, &fs->sb, from_parent_ino, &from_parent_inode);
1050 inode_load(fs->backing_fd, &fs->sb, to_parent_ino, &to_parent_inode);
1051 /* 디렉터리 여부 확인 */
1052 if ((from_parent_inode.mode & S_IFDIR) == 0 ||
1053 (to_parent_inode.mode & S_IFDIR) == 0) {
1054 free(from_copy);
1055 free(to_copy);
1056 return -ENOTDIR;
1057 }
1058
1059 uint8_t buf_block[SFUSE_BLOCK_SIZE];
1060 /* 원본 부모 디렉터리에서 엔트리 제거 */
1061 for (uint32_t i = 0; i < 12U; ++i) {
1062 if (from_parent_inode.direct[i] == 0)
1063 continue;
1064 read_block(fs->backing_fd, from_parent_inode.direct[i], buf_block);
1065 struct sfuse_dirent *entries = (struct sfuse_dirent *)buf_block;
1066 for (uint32_t j = 0; j < DENTS_PER_BLOCK; ++j) {
1067 if (entries[j].inode == src_ino &&
1068 strncmp(entries[j].name, from_name, SFUSE_NAME_MAX) == 0) {
1069 entries[j].inode = 0;
1070 entries[j].name[0] = '\0';
1071 write_block(fs->backing_fd, from_parent_inode.direct[i], entries);
1072 goto removed_src;
1073 }
1074 }
1075 }
1076removed_src:
1077
1078 /* 대상 부모 디렉터리에 엔트리 추가 */
1079 for (uint32_t i = 0; i < 12U; ++i) {
1080 if (to_parent_inode.direct[i] == 0) {
1081 int new_blk = alloc_block(&fs->sb, &fs->bmaps->block);
1082 if (new_blk < 0)
1083 break;
1084 to_parent_inode.direct[i] = new_blk;
1085 struct sfuse_dirent *entries = (struct sfuse_dirent *)buf_block;
1086 memset(entries, 0, sizeof(buf_block));
1087 entries[0].inode = src_ino;
1088 strncpy(entries[0].name, to_name, SFUSE_NAME_MAX - 1);
1089 entries[0].name[SFUSE_NAME_MAX - 1] = '\0';
1090 write_block(fs->backing_fd, to_parent_inode.direct[i], entries);
1091 to_parent_inode.size += SFUSE_BLOCK_SIZE;
1092 break;
1093 } else {
1094 read_block(fs->backing_fd, to_parent_inode.direct[i], buf_block);
1095 struct sfuse_dirent *entries = (struct sfuse_dirent *)buf_block;
1096 for (uint32_t k = 0; k < DENTS_PER_BLOCK; ++k) {
1097 if (entries[k].inode == 0) {
1098 entries[k].inode = src_ino;
1099 strncpy(entries[k].name, to_name, SFUSE_NAME_MAX - 1);
1100 write_block(fs->backing_fd, to_parent_inode.direct[i], entries);
1101 goto added_dst;
1102 }
1103 }
1104 }
1105 }
1106added_dst:
1107
1108 /* 메타데이터 갱신 */
1109 time_t now_time = time(NULL);
1110 from_parent_inode.mtime = from_parent_inode.ctime = (uint32_t)now_time;
1111 to_parent_inode.mtime = to_parent_inode.ctime = (uint32_t)now_time;
1112
1113 struct sfuse_inode src_inode;
1114 inode_load(fs->backing_fd, &fs->sb, src_ino, &src_inode);
1115 src_inode.ctime = (uint32_t)now_time;
1116
1117 inode_sync(fs->backing_fd, &fs->sb, src_ino, &src_inode);
1118 inode_sync(fs->backing_fd, &fs->sb, from_parent_ino, &from_parent_inode);
1119 inode_sync(fs->backing_fd, &fs->sb, to_parent_ino, &to_parent_inode);
1120
1121 free(from_copy);
1122 free(to_copy);
1123 return 0;
1124}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_resolve_path()

int fs_resolve_path ( struct sfuse_fs * fs,
const char * path,
uint32_t * out_ino )

경로를 inode 번호로 변환

매개변수
fs파일 시스템 컨텍스트
path변환할 경로 문자열
out_ino변환된 inode 번호 저장 위치
반환값
성공 시 0, 실패 시 음수 오류 코드

경로를 inode 번호로 변환

루트("/")는 inode 1로 처리하며, 경로를 '/' 구분자로 분할하여 순차 검색

매개변수
fs파일 시스템 컨텍스트 포인터
path변환할 경로 문자열 (null-terminated)
out_ino변환된 inode 번호를 저장할 포인터
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 198 번째 라인에서 정의되었습니다.

198 {
199 if (strcmp(path, "/") == 0) {
200 *out_ino = 1; /* 루트 inode */
201 return 0;
202 }
203
204 /* 경로 복사 및 분할 */
205 char *path_copy = strdup(path);
206 if (!path_copy)
207 return -ENOMEM;
208
209 uint32_t current = 1; /* 루트부터 시작 */
210 char *token = strtok(path_copy, "/");
211 while (token) {
212 uint32_t next;
213 int ret = dir_lookup(fs, current, token, &next);
214 if (ret < 0) {
215 free(path_copy);
216 return ret;
217 }
218 current = next;
219 token = strtok(NULL, "/");
220 }
221 free(path_copy);
222
223 *out_ino = current;
224 return 0;
225}
int dir_lookup(const struct sfuse_fs *fs, uint32_t dir_ino, const char *name, uint32_t *out_ino)
디렉터리에서 이름으로 inode 번호를 검색
Definition dir.c:18
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_rmdir()

int fs_rmdir ( struct sfuse_fs * fs,
const char * path )

디렉터리 삭제

매개변수
fs파일 시스템 컨텍스트
path삭제할 디렉터리 경로
반환값
성공 시 0, 실패 시 음수 오류 코드

디렉터리 삭제

지정된 경로의 디렉터리가 비어 있는지 확인한 후, fs_unlink 로직을 재사용하여 디렉터리를 제거한다.

매개변수
fs파일 시스템 컨텍스트 포인터
path삭제할 디렉터리 경로 (null-terminated 문자열)
반환값
성공 시 0, 실패 시 음수 오류 코드

fs.c 파일의 963 번째 라인에서 정의되었습니다.

963 {
964 uint32_t ino;
965 if (fs_resolve_path(fs, path, &ino) < 0) {
966 return -ENOENT;
967 }
968
969 struct sfuse_inode inode;
970 inode_load(fs->backing_fd, &fs->sb, ino, &inode);
971 /* 디렉터리인지 확인 */
972 if ((inode.mode & S_IFDIR) == 0) {
973 return -ENOTDIR;
974 }
975
976 /* 비어 있는지 확인 */
977 uint8_t block[SFUSE_BLOCK_SIZE];
978 for (int i = 0; i < 12; ++i) {
979 if (inode.direct[i] == 0)
980 continue;
981 if (read_block(fs->backing_fd, inode.direct[i], block) < 0)
982 continue;
983 struct sfuse_dirent *entries = (struct sfuse_dirent *)block;
984 for (uint32_t j = 0; j < DENTS_PER_BLOCK; ++j) {
985 if (entries[j].inode != 0) {
986 return -ENOTEMPTY;
987 }
988 }
989 }
990
991 /* fs_unlink 로직 재사용 */
992 char *dummy_path = strdup(path);
993 if (!dummy_path)
994 return -ENOMEM;
995 int res = fs_unlink(fs, path);
996 free(dummy_path);
997 return res;
998}
int fs_unlink(struct sfuse_fs *fs, const char *path)
파일 삭제
Definition fs.c:829
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_teardown()

void fs_teardown ( struct sfuse_fs * fs)

파일 시스템 정리

매개변수
fs해제할 파일 시스템 컨텍스트

파일 시스템 정리

슈퍼블록과 비트맵을 디스크에 동기화하고, 할당된 메모리 및 파일 디스크립터 정리

매개변수
fs해제할 파일 시스템 컨텍스트 포인터

fs.c 파일의 165 번째 라인에서 정의되었습니다.

165 {
166 if (!fs)
167 return;
168
169 /* 슈퍼블록 동기화 */
170 sb_sync(fs->backing_fd, &fs->sb);
171
172 /* 비트맵 동기화 */
173 uint32_t bits_per_block = SFUSE_BLOCK_SIZE * 8;
174 uint32_t im_blocks =
175 (fs->sb.total_inodes + bits_per_block - 1) / bits_per_block;
176 uint32_t bm_blocks =
177 (fs->sb.total_blocks + bits_per_block - 1) / bits_per_block;
179 im_blocks + bm_blocks);
180
181 /* 메모리 및 파일 디스크립터 정리 */
182 free(fs->inode_table);
183 free(fs->bmaps);
184 close(fs->backing_fd);
185 free(fs);
186}
int bitmap_sync(int fd, uint32_t start_blk, const struct sfuse_bitmaps *bmaps, uint32_t count)
메모리 비트맵을 디스크에 동기화
Definition bitmap.c:40
struct sfuse_inode_block * inode_table
Definition fs.h:25
uint32_t total_inodes
Definition super.h:53
uint32_t inode_bitmap_start
Definition super.h:57
uint32_t total_blocks
Definition super.h:54
int sb_sync(int fd, const struct sfuse_superblock *sb)
슈퍼블록을 디스크에 동기화
Definition super.c:40
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_truncate()

int fs_truncate ( struct sfuse_fs * fs,
const char * path,
off_t size )

파일 크기 조정 (truncate)

매개변수
fs파일 시스템 컨텍스트
path대상 파일 경로
size새로운 파일 크기
반환값
성공 시 0, 실패 시 음수 오류 코드

파일 크기 조정 (truncate)

지정된 경로의 파일 크기를 주어진 크기로 변경. 크기 축소 시 불필요한 데이터 블록을 해제하고, 크기 확장 시 필요한 경우 단일 바이트 쓰기를 통해 공간을 확보.

매개변수
fs파일 시스템 컨텍스트 포인터
path대상 파일 경로 (null-terminated 문자열)
size새 파일 크기 (바이트 단위)
반환값
성공 시 0, 실패 시 음수 오류 코드

< 유지할 블록 수

< 기존 블록 수

< 1차 인덱스

< 2차 인덱스

< 파일 크기 갱신

< 수정 시간 갱신

< 변경 시간 갱신

fs.c 파일의 1138 번째 라인에서 정의되었습니다.

1138 {
1139 uint32_t ino;
1140 if (fs_resolve_path(fs, path, &ino) < 0) {
1141 return -ENOENT;
1142 }
1143
1144 struct sfuse_inode inode;
1145 inode_load(fs->backing_fd, &fs->sb, ino, &inode);
1146
1147 /* 디렉터리인 경우 오류 반환 */
1148 if ((inode.mode & S_IFDIR) == S_IFDIR) {
1149 return -EISDIR;
1150 }
1151
1152 off_t old_size = inode.size;
1153 /* 변경할 크기가 동일하면 즉시 반환 */
1154 if (size == old_size) {
1155 return 0;
1156 }
1157 /* 크기 축소 */
1158 else if (size < old_size) {
1159 uint32_t keep_blocks =
1161 uint32_t old_blocks = (old_size + SFUSE_BLOCK_SIZE - 1) /
1163
1164 /* 축소되어야 할 블록 해제 */
1165 for (uint32_t i = keep_blocks; i < old_blocks; ++i) {
1166 if (i < 12) {
1167 if (inode.direct[i] != 0) {
1168 free_block(&fs->sb, &fs->bmaps->block, inode.direct[i]);
1169 inode.direct[i] = 0;
1170 }
1171 } else if (i < 12U + SFUSE_PTRS_PER_BLOCK) {
1172 if (inode.indirect != 0) {
1173 uint32_t ptrs[SFUSE_PTRS_PER_BLOCK];
1174 read_block(fs->backing_fd, inode.indirect, ptrs);
1175 int idx = i - 12;
1176 if (ptrs[idx] != 0) {
1177 free_block(&fs->sb, &fs->bmaps->block, ptrs[idx]);
1178 ptrs[idx] = 0;
1179 }
1180 write_block(fs->backing_fd, inode.indirect, ptrs);
1181 }
1182 } else {
1183 if (inode.double_indirect != 0) {
1184 uint32_t level1_arr[SFUSE_PTRS_PER_BLOCK];
1185 read_block(fs->backing_fd, inode.double_indirect, level1_arr);
1186 uint32_t idx = i - (12 + SFUSE_PTRS_PER_BLOCK);
1187 uint32_t l1_idx = idx / SFUSE_PTRS_PER_BLOCK;
1188 uint32_t l2_idx = idx % SFUSE_PTRS_PER_BLOCK;
1189
1190 if (level1_arr[l1_idx] != 0) {
1191 uint32_t level2_arr[SFUSE_PTRS_PER_BLOCK];
1192 read_block(fs->backing_fd, level1_arr[l1_idx], level2_arr);
1193 if (level2_arr[l2_idx] != 0) {
1194 free_block(&fs->sb, &fs->bmaps->block, level2_arr[l2_idx]);
1195 level2_arr[l2_idx] = 0;
1196 }
1197 write_block(fs->backing_fd, level1_arr[l1_idx], level2_arr);
1198 }
1199 }
1200 }
1201 }
1202
1203 /* 단일 간접 블록 전체가 비었는지 확인 후 해제 */
1204 if (inode.indirect != 0) {
1205 uint32_t ptrs[SFUSE_PTRS_PER_BLOCK];
1206 read_block(fs->backing_fd, inode.indirect, ptrs);
1207 int all_empty = 1;
1208 for (uint32_t j = 0; j < SFUSE_PTRS_PER_BLOCK; ++j) {
1209 if (ptrs[j] != 0) {
1210 all_empty = 0;
1211 break;
1212 }
1213 }
1214 if (all_empty) {
1215 free_block(&fs->sb, &fs->bmaps->block, inode.indirect);
1216 inode.indirect = 0;
1217 }
1218 }
1219
1220 /* 이중 간접 블록 전체가 비었는지 확인 후 해제 */
1221 if (inode.double_indirect != 0) {
1222 uint32_t level1[SFUSE_PTRS_PER_BLOCK];
1223 read_block(fs->backing_fd, inode.double_indirect, level1);
1224 int all_l1_empty = 1;
1225 for (uint32_t a = 0; a < SFUSE_PTRS_PER_BLOCK; ++a) {
1226 if (level1[a] != 0) {
1227 uint32_t level2[SFUSE_PTRS_PER_BLOCK];
1228 read_block(fs->backing_fd, level1[a], level2);
1229 int all_l2_empty = 1;
1230 for (uint32_t b = 0; b < SFUSE_PTRS_PER_BLOCK; ++b) {
1231 if (level2[b] != 0) {
1232 all_l2_empty = 0;
1233 break;
1234 }
1235 }
1236 if (all_l2_empty) {
1237 free_block(&fs->sb, &fs->bmaps->block, level1[a]);
1238 level1[a] = 0;
1239 } else {
1240 all_l1_empty = 0;
1241 }
1242 }
1243 }
1244 if (all_l1_empty) {
1245 free_block(&fs->sb, &fs->bmaps->block, inode.double_indirect);
1246 inode.double_indirect = 0;
1247 } else {
1248 write_block(fs->backing_fd, inode.double_indirect, level1);
1249 }
1250 }
1251
1252 inode.size = size;
1253 }
1254 /* 크기 확장 */
1255 else {
1256 char zero = 0;
1257 if (fs_write(fs, path, &zero, 1, size - 1) < 0) {
1258 return -EIO;
1259 }
1260 return 0;
1261 }
1262
1263 /* 시간 정보 갱신 및 동기화 */
1264 time_t now_time = time(NULL);
1265 inode.mtime = (uint32_t)now_time;
1266 inode.ctime = (uint32_t)now_time;
1267 inode_sync(fs->backing_fd, &fs->sb, ino, &inode);
1268 return 0;
1269}
void free_block(struct sfuse_superblock *sb, struct sfuse_block_bitmap *bmap, uint32_t blk)
슈퍼블록 기반으로 데이터 블록 해제
Definition bitmap.c:135
int fs_write(struct sfuse_fs *fs, const char *path, const char *buf, size_t size, off_t offset)
파일 쓰기
Definition fs.c:407
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_unlink()

int fs_unlink ( struct sfuse_fs * fs,
const char * path )

파일 삭제

매개변수
fs파일 시스템 컨텍스트
path삭제할 파일 경로
반환값
성공 시 0, 실패 시 음수 오류 코드

지정된 경로의 파일을 삭제하고, 관련 데이터 블록 및 아이노드를 해제한다.

매개변수
fs파일 시스템 컨텍스트 포인터
path삭제할 파일 경로 (null-terminated 문자열)
반환값
성공 시 0, 실패 시 음수 오류 코드

< 파일/디렉터리 이름의 최대 길이

fs.c 파일의 829 번째 라인에서 정의되었습니다.

829 {
830 uint32_t ino;
831 if (fs_resolve_path(fs, path, &ino) < 0) {
832 return -ENOENT;
833 }
834
835 struct sfuse_inode inode;
836 inode_load(fs->backing_fd, &fs->sb, ino, &inode);
837 /* 디렉터리는 삭제 불가 */
838 if ((inode.mode & S_IFDIR) == S_IFDIR) {
839 return -EISDIR;
840 }
841
842 /* 상위 디렉터리 및 파일 이름 분리 */
843 char *path_copy = strdup(path);
844 if (!path_copy)
845 return -ENOMEM;
846 char *name = strrchr(path_copy, '/');
847 *name = '\0';
848 char *parent_path = (*path_copy == '\0') ? "/" : path_copy;
849 name++;
850
851 /* 상위 디렉터리 inode 조회 */
852 uint32_t parent_ino;
853 fs_resolve_path(fs, parent_path, &parent_ino);
854
855 uint8_t dir_block[SFUSE_BLOCK_SIZE];
856 uint8_t zero_block[SFUSE_BLOCK_SIZE] = {0}; /* 블록 초기화용 제로 버퍼 */
857 struct sfuse_inode parent_inode;
858 inode_load(fs->backing_fd, &fs->sb, parent_ino, &parent_inode);
859
860 /* 상위 디렉터리에서 디렉터리 엔트리 제거 */
861 for (uint32_t i = 0; i < 12; ++i) {
862 if (parent_inode.direct[i] == 0)
863 continue;
864 if (read_block(fs->backing_fd, parent_inode.direct[i], dir_block) < 0)
865 continue;
866 struct sfuse_dirent *entries = (struct sfuse_dirent *)dir_block;
867 for (uint32_t j = 0; j < DENTS_PER_BLOCK; ++j) {
868 if (entries[j].inode == ino &&
869 strncmp(entries[j].name, name, SFUSE_NAME_MAX) == 0) {
870 /* 삭제 시 디렉터리 엔트리 전체를 0으로 초기화 */
871 memset(&entries[j], 0, sizeof(entries[j]));
872 write_block(fs->backing_fd, parent_inode.direct[i], dir_block);
873 goto found_entry;
874 }
875 }
876 }
877found_entry:
878
879 /* 직접 데이터 블록 해제: 내용 제로화 후 상대 인덱스로 비트맵 해제 */
880 for (int i = 0; i < 12; ++i) {
881 if (inode.direct[i] == 0)
882 continue;
883 write_block(fs->backing_fd, inode.direct[i],
884 zero_block); // 블록 내용 모두 0으로 덮어쓰기
885 free_block(&fs->sb, &fs->bmaps->block,
886 inode.direct[i] -
887 fs->sb.data_block_start); // 상대 블록 번호로 비트맵 해제
888 inode.direct[i] = 0;
889 }
890
891 /* 단일 간접 블록 해제: 데이터 블록과 포인터 블록 모두 제로화 후 해제 */
892 if (inode.indirect != 0) {
893 uint32_t ptrs[SFUSE_PTRS_PER_BLOCK];
894 read_block(fs->backing_fd, inode.indirect, ptrs);
895 for (uint32_t k = 0; k < SFUSE_PTRS_PER_BLOCK; ++k) {
896 if (ptrs[k] == 0)
897 continue;
898 write_block(fs->backing_fd, ptrs[k], zero_block);
899 free_block(&fs->sb, &fs->bmaps->block, ptrs[k] - fs->sb.data_block_start);
900 ptrs[k] = 0;
901 }
902 write_block(fs->backing_fd, inode.indirect,
903 zero_block); // 포인터 블록도 제로화
904 free_block(&fs->sb, &fs->bmaps->block,
905 inode.indirect - fs->sb.data_block_start);
906 inode.indirect = 0;
907 }
908
909 /* 이중 간접 블록 해제: 이중 레벨 순회하며 제로화 후 해제 */
910 if (inode.double_indirect != 0) {
911 uint32_t l1[SFUSE_PTRS_PER_BLOCK];
912 read_block(fs->backing_fd, inode.double_indirect, l1);
913 for (uint32_t i1 = 0; i1 < SFUSE_PTRS_PER_BLOCK; ++i1) {
914 if (l1[i1] == 0)
915 continue;
916 uint32_t l2[SFUSE_PTRS_PER_BLOCK];
917 read_block(fs->backing_fd, l1[i1], l2);
918 for (uint32_t i2 = 0; i2 < SFUSE_PTRS_PER_BLOCK; ++i2) {
919 if (l2[i2] == 0)
920 continue;
921 write_block(fs->backing_fd, l2[i2], zero_block);
922 free_block(&fs->sb, &fs->bmaps->block,
923 l2[i2] - fs->sb.data_block_start);
924 l2[i2] = 0;
925 }
926 write_block(fs->backing_fd, l1[i1], zero_block); // 2차 포인터 블록 제로화
927 free_block(&fs->sb, &fs->bmaps->block, l1[i1] - fs->sb.data_block_start);
928 l1[i1] = 0;
929 }
930 write_block(fs->backing_fd, inode.double_indirect,
931 zero_block); // 1차 포인터 블록 제로화
932 free_block(&fs->sb, &fs->bmaps->block,
933 inode.double_indirect - fs->sb.data_block_start);
934 inode.double_indirect = 0;
935 }
936
937 /* 아이노드 비트맵 해제 및 아이노드 초기화 */
938 free_inode(&fs->sb, &fs->bmaps->inode, ino);
939 struct sfuse_inode empty_inode;
940 memset(&empty_inode, 0, sizeof(empty_inode));
941 inode_sync(fs->backing_fd, &fs->sb, ino, &empty_inode);
942
943 /* 상위 디렉터리 메타데이터 갱신 */
944 time_t now_time = time(NULL);
945 parent_inode.mtime = (uint32_t)now_time;
946 parent_inode.ctime = (uint32_t)now_time;
947 inode_sync(fs->backing_fd, &fs->sb, parent_ino, &parent_inode);
948
949 free(path_copy);
950 return 0;
951}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_utimens()

int fs_utimens ( struct sfuse_fs * fs,
const char * path,
const struct timespec tv[2] )

파일의 시간 속성 변경 (utimens)

매개변수
fs파일 시스템 컨텍스트
path대상 경로
tv[0]=접근 시간, [1]=변경 시간
반환값
성공 시 0, 실패 시 음수 오류 코드

파일의 시간 속성 변경 (utimens)

매개변수
fs파일 시스템 컨텍스트 포인터
path대상 경로 (null-terminated 문자열)
tvtv[0]=접근 시간, tv[1]=수정 시간
반환값
성공 시 0, 실패 시 음수 오류 코드

< 접근 시간 설정

< 수정 시간 설정

< 메타데이터 변경 시간 갱신

fs.c 파일의 1318 번째 라인에서 정의되었습니다.

1319 {
1320 uint32_t ino;
1321 if (fs_resolve_path(fs, path, &ino) < 0) {
1322 return -ENOENT;
1323 }
1324 struct sfuse_inode inode;
1325 if (inode_load(fs->backing_fd, &fs->sb, ino, &inode) < 0) {
1326 return -EIO;
1327 }
1328 inode.atime = (uint32_t)tv[0].tv_sec;
1329 inode.mtime = (uint32_t)tv[1].tv_sec;
1330 inode.ctime = (uint32_t)time(NULL);
1331 inode_sync(fs->backing_fd, &fs->sb, ino, &inode);
1332 return 0;
1333}
uint32_t atime
Definition inode.h:27
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ fs_write()

int fs_write ( struct sfuse_fs * fs,
const char * path,
const char * buf,
size_t size,
off_t offset )

파일 쓰기

매개변수
fs파일 시스템 컨텍스트
path파일 경로
buf쓸 데이터 버퍼
size쓸 바이트 수
offset쓰기 오프셋
반환값
쓴 바이트 수 또는 음수 오류 코드

지정된 경로의 파일에 사용자 버퍼의 데이터를 기록한다.

매개변수
fs파일 시스템 컨텍스트 포인터
path쓰기 대상 파일 경로 (null-terminated 문자열)
buf기록할 데이터가 담긴 버퍼 포인터
size기록할 바이트 수
offset파일 내 시작 오프셋 (바이트 단위)
반환값
기록된 바이트 수 (>=0), 실패 시 음수 오류 코드

< 현재 오프셋

< 논리 블록 인덱스

< 블록 내 오프셋

< 블록 경계까지 쓸 바이트

< 대상 블록 포인터 위치

< 실제 할당된 디스크 블록 번호

< 1차 인덱스

< 2차 인덱스

< 수정 시간 갱신

< 변경 시간 갱신

fs.c 파일의 407 번째 라인에서 정의되었습니다.

408 {
409 uint32_t ino;
410 if (fs_resolve_path(fs, path, &ino) < 0)
411 return -ENOENT;
412
413 struct sfuse_inode inode;
414 if (inode_load(fs->backing_fd, &fs->sb, ino, &inode) < 0)
415 return -EIO;
416
417 /*< 디렉터리에는 쓰기 불가 */
418 if ((inode.mode & S_IFDIR) == S_IFDIR)
419 return -EISDIR;
420
421 size_t bytes_written = 0;
422 uint8_t block_buf[SFUSE_BLOCK_SIZE];
423
424 /*< 요청한 크기만큼 반복 처리 */
425 while (bytes_written < size) {
426 off_t cur_offset = offset + bytes_written;
427 uint32_t block_index =
428 cur_offset / SFUSE_BLOCK_SIZE;
429 uint32_t block_offset =
430 cur_offset % SFUSE_BLOCK_SIZE;
431 size_t to_write =
432 SFUSE_BLOCK_SIZE - block_offset;
433 if (to_write > size - bytes_written)
434 to_write = size - bytes_written;
435
436 uint32_t *target = NULL;
437 uint32_t disk_block = 0;
438
439 /*< 직접 블록 */
440 if (block_index < 12U) {
441 target = &inode.direct[block_index];
442 disk_block = *target; /* direct 블록 포인터로 disk_block 초기화 */
443 }
444 /*< 단일 간접 블록 */
445 else if (block_index < 12U + SFUSE_PTRS_PER_BLOCK) {
446 if (inode.indirect == 0) {
447 /* 간접 블록이 없으면 새 할당 */
448 int new_block = alloc_block(&fs->sb, &fs->bmaps->block);
449 if (new_block < 0)
450 return -ENOSPC;
451 inode.indirect =
452 (uint32_t)(fs->sb.data_block_start +
453 new_block); /* 간접 블록 주소도 절대 번호로 변환 */
454 uint32_t tmp[SFUSE_PTRS_PER_BLOCK] = {0};
455 write_block(fs->backing_fd, inode.indirect, tmp);
456 }
457 /* 기존 간접 블록에서 포인터 읽기 */
458 uint32_t ptrs[SFUSE_PTRS_PER_BLOCK];
459 read_block(fs->backing_fd, inode.indirect, ptrs);
460
461 target = &ptrs[block_index - 12U];
462 disk_block = *target;
463
464 /* 새 데이터 블록 할당 */
465 if (disk_block == 0) {
466 int new_block = alloc_block(&fs->sb, &fs->bmaps->block);
467 if (new_block < 0)
468 return -ENOSPC;
469 disk_block = (uint32_t)(fs->sb.data_block_start +
470 new_block); /* 새 블록 인덱스를 데이터 영역
471 오프셋과 합산 */
472 *target = disk_block;
473 write_block(fs->backing_fd, inode.indirect, ptrs);
474 }
475 }
476 /*< 이중 간접 블록 */
477 else {
478 uint32_t dbl_index = block_index - (12U + SFUSE_PTRS_PER_BLOCK);
479 uint32_t l1_idx = dbl_index / SFUSE_PTRS_PER_BLOCK;
480 uint32_t l2_idx = dbl_index % SFUSE_PTRS_PER_BLOCK;
481
482 if (inode.double_indirect == 0) {
483 int new_block = alloc_block(&fs->sb, &fs->bmaps->block);
484 if (new_block < 0)
485 return -ENOSPC;
486 inode.double_indirect =
487 (uint32_t)(fs->sb.data_block_start +
488 new_block); /* 이중 간접 블록도 절대 번호로 변환 */
489 uint32_t tmp[SFUSE_PTRS_PER_BLOCK] = {0};
490 write_block(fs->backing_fd, inode.double_indirect, tmp);
491 }
492
493 uint32_t l1[SFUSE_PTRS_PER_BLOCK];
494 read_block(fs->backing_fd, inode.double_indirect, l1);
495
496 if (l1[l1_idx] == 0) {
497 int new_block = alloc_block(&fs->sb, &fs->bmaps->block);
498 if (new_block < 0)
499 return -ENOSPC;
500 l1[l1_idx] = (uint32_t)(fs->sb.data_block_start +
501 new_block); /* 레벨1 인덱스에도 데이터 영역 시작
502 오프셋 적용 */
503 uint32_t tmp[SFUSE_PTRS_PER_BLOCK] = {0};
504 write_block(fs->backing_fd, l1[l1_idx], tmp);
505 write_block(fs->backing_fd, inode.double_indirect, l1);
506 }
507
508 uint32_t l2[SFUSE_PTRS_PER_BLOCK];
509 read_block(fs->backing_fd, l1[l1_idx], l2);
510
511 if (l2[l2_idx] == 0) {
512 int new_block = alloc_block(&fs->sb, &fs->bmaps->block);
513 if (new_block < 0)
514 return -ENOSPC;
515 l2[l2_idx] = (uint32_t)(fs->sb.data_block_start +
516 new_block); /* 레벨2 인덱스에도 오프셋을 더해
517 절대 주소로 */
518 write_block(fs->backing_fd, l1[l1_idx], l2);
519 }
520
521 disk_block = l2[l2_idx];
522 target = &l2[l2_idx];
523 }
524
525 /*< 아직 할당되지 않았으면 새로 할당 */
526 if (target && *target == 0) {
527 int new_block = alloc_block(&fs->sb, &fs->bmaps->block);
528 if (new_block < 0)
529 return -ENOSPC;
530 *target = (uint32_t)(fs->sb.data_block_start +
531 new_block); /* 상대 인덱스에 데이터 영역 시작 블록
532 번호 더해 절대 블록 번호로 저장 */
533 disk_block = *target;
534 }
535
536 /*< 기존 블록 읽기 */
537 if (read_block(fs->backing_fd, disk_block, block_buf) < 0)
538 return -EIO;
539
540 /*< 데이터 쓰기 */
541 memcpy(block_buf + block_offset, buf + bytes_written, to_write);
542 if (write_block(fs->backing_fd, disk_block, block_buf) < 0)
543 return -EIO;
544
545 bytes_written += to_write;
546 }
547
548 /*< 파일 크기 갱신 */
549 if ((uint32_t)(offset + bytes_written) > inode.size)
550 inode.size = offset + bytes_written;
551 inode.mtime = time(NULL);
552 inode.ctime = inode.mtime;
553 if (inode_sync(fs->backing_fd, &fs->sb, ino, &inode) < 0)
554 return -EIO;
555
556 return bytes_written;
557}
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ sfuse_get_operations()

struct fuse_operations * sfuse_get_operations ( void )

SFUSE용 FUSE operations 구조체 반환

반환값
설정된 fuse_operations 포인터

SFUSE용 FUSE operations 구조체 반환

생성된 콜백 함수들을 ops 구조체에 등록하여 반환한다.

반환값
설정된 fuse_operations 구조체 포인터

ops.c 파일의 232 번째 라인에서 정의되었습니다.

232 {
233 static struct fuse_operations ops;
234 memset(&ops, 0, sizeof(ops));
235 ops.getattr = sfuse_getattr_cb;
236 ops.access = sfuse_access_cb;
237 ops.readdir = sfuse_readdir_cb;
238 ops.open = sfuse_open_cb;
239 ops.read = sfuse_read_cb;
240 ops.write = sfuse_write_cb;
241 ops.create = sfuse_create_cb;
242 ops.mkdir = sfuse_mkdir_cb;
243 ops.unlink = sfuse_unlink_cb;
244 ops.rmdir = sfuse_rmdir_cb;
245 ops.rename = sfuse_rename_cb;
246 ops.truncate = sfuse_truncate_cb;
247 ops.flush = sfuse_flush_cb;
248 ops.fsync = sfuse_fsync_cb;
249 ops.utimens = sfuse_utimens_cb;
250 return &ops;
251}
static int sfuse_truncate_cb(const char *path, off_t size, struct fuse_file_info *fi)
파일 크기 변경 콜백
Definition ops.c:175
static int sfuse_fsync_cb(const char *path, int datasync, struct fuse_file_info *fi)
fsync 콜백
Definition ops.c:218
static int sfuse_read_cb(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
파일 읽기 콜백
Definition ops.c:82
static int sfuse_open_cb(const char *path, struct fuse_file_info *fi)
파일 열기 콜백
Definition ops.c:67
static int sfuse_rename_cb(const char *from, const char *to, unsigned int flags)
이름 변경 콜백
Definition ops.c:160
static int sfuse_getattr_cb(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
파일/디렉터리 속성 조회 콜백
Definition ops.c:21
static int sfuse_create_cb(const char *path, mode_t mode, struct fuse_file_info *fi)
파일 생성 콜백
Definition ops.c:112
static int sfuse_utimens_cb(const char *path, const struct timespec tv[2], struct fuse_file_info *fi)
파일/디렉터리 타임스탬프 갱신 콜백
Definition ops.c:190
static int sfuse_unlink_cb(const char *path)
파일 삭제 콜백
Definition ops.c:136
static int sfuse_write_cb(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
파일 쓰기 콜백
Definition ops.c:98
static int sfuse_mkdir_cb(const char *path, mode_t mode)
디렉터리 생성 콜백
Definition ops.c:125
static int sfuse_readdir_cb(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags)
디렉터리 목록 조회 콜백
Definition ops.c:51
static int sfuse_access_cb(const char *path, int mask)
access 콜백
Definition ops.c:35
static int sfuse_rmdir_cb(const char *path)
디렉터리 삭제 콜백
Definition ops.c:147
static int sfuse_flush_cb(const char *path, struct fuse_file_info *fi)
flush 콜백
Definition ops.c:204
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

변수 문서화

◆ g_force_format

bool g_force_format = false
extern

강제 포맷 옵션 플래그

< fs_initialize, fs_teardown, g_force_format extern

main.c에서 정의되며, fs_initialize에서 VSFS 포맷을 강제할 때 사용됩니다.

강제 포맷 옵션 플래그

이 플래그는 main.c에서 정의되며, FS 초기화 시 포맷을 강제할 때 사용됩니다.

< fs_initialize, fs_teardown, g_force_format extern

main.c에서 정의되며, fs_initialize에서 VSFS 포맷을 강제할 때 사용됩니다.

main.c 파일의 32 번째 라인에서 정의되었습니다.