2012. 7. 13. 16:09

파일의 소유자 id,groupid,최근 파일변경 시간을 알아내는 예제

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

main(int argc, char *argv[])
{
   struct stat st;

   /* argv[1] 파일에 대한 정보가 st에 저장 */
   if (stat(argv[1], &st) == -1) {
      perror("stat failed");
      exit(1);
   }
   /* st.st_size는 파일의 크기, st.st_uid는 파일 소유자 ID, st.st_mtime는 파일에
     대한 최종 수정 시간으로, ctime은 시간 정보를 문자열로 변환하는 함수 */
   printf("%ld byte, user-id %d, group-id %d, modify time %s", st.st_size, st.st_uid, st.st_gid, ctime(&st.st_mtime));
   exit(0);
}

---------------------------------------------------------------------------------------------------
어느 파일이 더 최근에 수정된 것인지를 알아내는 예제

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

main(int argc, char *argv[])
{
   struct stat st1, st2;

   if (stat(argv[1], &st1) == -1) {
      perror("stat failed");
      exit(1);
   }
   if (stat(argv[2], &st2) == -1) {
      perror("stat failed");
      exit(1);
   }
   /* st1.st_mtime이 크면 argv[1]이 선택되고 그렇지 않으면 argv[2]가 선택 */
   printf("%s is up-to-date file\n", (st1.st_mtime > st2.st_mtime) ? argv[1] : argv[2]);
   exit(0);
}

---------------------------------------------------------------------------------------------------
파일형식 관련 매크로를 이용하여 stat에서 얻어온 st_mode를 16진수로 출력하는 프로그램

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

main(int argc, char *argv[])
{
   int i;
   struct stat st;

   for (i=1; i<argc; i++) {
      if (stat(argv[i], &st) == -1) {
         perror("stat failed");
         exit(1);
      }
      /* 파일 형식과 접근 권한 등의 정보를 저장하고 있는 st.st_mode를
         16진수 형태로 출력하는데, 4자리 중 첫 번째 수는 파일 형식을 나타냄 */
      printf("%s's mode : %x\n", argv[i], st.st_mode);
   }

   exit(0);
}

---------------------------------------------------------------------------------------------------
파일과 st_mode와의 AND 연산을 이용하여 정규파일 인지를 알아내는 예제

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

main(int argc, char *argv[])
{
   struct stat st;

   if (stat(argv[1], &st) == -1) {
      perror("stat failed");
      exit(1);
   }

   /* st.st_mode & S_IFMT(0x8000)은 파일 형식을 알아내는 수식 */
   switch (st.st_mode & S_IFMT) {
      case S_IFREG:   /* 정규 파일이면 */
         printf("regular\n");
         break;
      case S_IFDIR:   /* 디렉토리이면 */
         printf("directory\n");
         break;
      case S_IFCHR:   /* 문자 특수 파일이면 */
         printf("character special\n");
         break;
      case S_IFBLK:   /* 블록 특수 파일이면 */
         printf("block special\n");
         break;
      case S_IFIFO:   /* FIFO 파일이면 */
         printf("fifo\n");
   }
   exit(0);
}

---------------------------------------------------------------------------------------------------
파일형식을 좀더 쉽게 알아내는 매크로를 이용한 프로그램 if(S_ISREG(st.st_mode))

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

main(int argc, char *argv[])
{
   struct stat st;

   if (stat(argv[1], &st) == -1) {
      perror("stat failed");
      exit(1);
   }

   if(S_ISREG(st.st_mode)) {   /* 정규 파일이면 */
      printf("regular\n");
   } else if(S_ISDIR(st.st_mode)) {   /* 디렉토리이면 */
      printf("directory\n");
   } else if(S_ISCHR(st.st_mode)) {   /* 문자 특수 파일이면 */
      printf("character special\n");
   } else if(S_ISBLK(st.st_mode)) {   /* 블록 특수 파일이면 */
      printf("block special\n");
   } else if(S_ISFIFO(st.st_mode)) {   /* FIFO 파일이면 */
      printf("fifo\n");
   }
   exit(0);
}

---------------------------------------------------------------------------------------------------
st_mode에는 접근권한 정보도 포함되어 있다. ex)S_IXOTH 0000001(8진수) 다른 사용자의 실행권한
ex)소유자는 읽기,쓰기,실행 권한을 가지게 하고 그룹을 포함한 다른 사용자들은 읽기와 실행 권한만을
가지게 하는것
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH |S_IXOTH
0700 + 0040 + 0010 + 0004 + 0001 = 0755
8진수와 2진수 표현이 쉬우므로 많이 사용

파일의 접근 권한을 알아내는 프로그램(AND 연산을 이용)

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

main(int argc, char *argv[])
{
   struct stat st;

   if (stat(argv[1], &st) == -1) {
      perror("stat failed");
      exit(1);
   }

   /* (st.st_mode & S_IRUSR) 수식은 소유자에게 읽기 권한이 있는지를
      파악하는 식으로 참이면 “read ”가 선택되고 거짓이면 “”이 선택 */
   printf("user: %s%s%s\n", (st.st_mode & S_IRUSR)?"read ":"", (st.st_mode & S_IWUSR)?"write ":"",(st.st_mode & S_IXUSR)?"execute":"");
   printf("group: %s%s%s\n", (st.st_mode & S_IRGRP)?"read ":"", (st.st_mode & S_IWGRP)?"write ":"",(st.st_mode & S_IXGRP)?"execute":"");
   printf("others: %s%s%s\n", (st.st_mode & S_IROTH)?"read ":"", (st.st_mode & S_IWOTH)?"write ":"",(st.st_mode & S_IXOTH)?"execute":"");
   exit(0);
}

---------------------------------------------------------------------------------------------------
디렉토리를 생성했다가 삭제하는 단순한 프로그램

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

main()
{
   /* dir 디렉토리를 0755 권한으로 생성 */
   if(mkdir("dir", 0755) == -1) {
      perror("mkdir failed");
      exit(1);
   }
   /* dir 디렉토리를 삭제 */
   if(rmdir("dir") == -1) {
      perror("rmdir failed");
      exit(2);
   }
   exit(0);
}

---------------------------------------------------------------------------------------------------
디렉토리를 생성하고 생성된 디렉토리에 파일을 저장하는 프로그램

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>   /* strlen 함수가 정의된 헤더 파일 */

main(int argc, char *argv[])
{
   int fd;

   if(mkdir(argv[1], 0755) == -1) {   /* argv[1] 디렉토리를 생성 */
      perror("mkdir failed");
      exit(1);
   }

   if(chdir(argv[1]) == -1) {   /* argv[1] 디렉토리로 이동 */
      perror("chdir failed");
      exit(1);
   }

   /* argv[2] 파일을 쓰기 전용으로 여는데 만약 파일이 없으면 생성 */
   if((fd=open(argv[2], O_WRONLY | O_CREAT, 0644)) == -1) {
      perror("open failed");
      exit(1);
   }

   write(fd, argv[3], strlen(argv[3]));   /* fd 파일에 argv[3] 문자열 쓰기 */

   close(fd);
   exit(0);
}

---------------------------------------------------------------------------------------------------
현재작업 디렉토리 이름을 출력하고 생성한 argv[1] 디렉토리로 이동하여 디렉토리 이름을 출력
다시 상위 디렉토리로 이동하여 디렉토리 이름을 출력하고 argv[1] 디렉토리 삭제

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX 100

main(int argc, char *argv[])
{
   char name[MAX];

   /* 현재 작업 디렉토리 이름을 알아내서 출력 */
   getcwd(name, MAX);
   printf("directory name : %s\n", name);

   /* argv[1] 디렉토리를 생성하고 이동 */
   mkdir(argv[1], 0755);
   chdir(argv[1]);
   getcwd(name, MAX);/* 현재 작업 디렉토리를 얻어옴 */
   printf("directory name : %s\n", name);

   /* 상위 디렉토리로 이동 */
   chdir("..");
   getcwd(name, MAX);
   printf("directory name : %s\n", name);

   /* argv[1] 디렉토리를 삭제 */
   rmdir(argv[1]);

   exit(0);
}

---------------------------------------------------------------------------------------------------
typedef struct {
...
} DIR;
생성한 dir 디렉토리를 opendir에 의해 열고 closedir로 닫는 단순한 프로그램

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

main()
{
   DIR *dp;   /* 디렉토리 정보에 대한 포인터 */

   if(mkdir("dir", 0755) == -1) {   /* dir 디렉토리를 생성 */
      perror("mkdir failed");
      exit(1);
   }
   /* dir 디렉토리를 여는데 디렉토리 정보에 대한 포인터가 반환 */
   if((dp=opendir("dir")) == NULL) {
      perror("opendir failed");
      exit(1);
   }
   closedir(dp);   /* dp 디렉토리 닫기 */
   exit(0);
}

---------------------------------------------------------------------------------------------------
opendir에 의해 연 디렉토리의 모든 항복들의 이름을 출력하는 프로그램. 더 이상 읽을 항목이 없으면
NULL이 반환

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

main()
{
   DIR *dp;   /* 디렉토리 정보에 대한 포인터 */
   struct dirent *dirp;   /* 디렉토리의 한 항목의 정보에 대한 포인터 */

   if((dp=opendir(".")) == NULL) {   /* 현재(.) 디렉토리 열기 */
      perror("opendir failed");
      exit(1);
   }
   /* dp 디렉토리의 항목들을 하나씩 읽어서 항목 이름을 출력한다.
     더 이상 읽을 항목이 없으면 NULL이 반환된다. */
   while (dirp=readdir(dp)) {
      printf("%s ", dirp->d_name);
   }
   printf("\n");
   closedir(dp);   /* dp 디렉토리 닫기 */
   exit(0);
}

---------------------------------------------------------------------------------------------------
argv[1] 디렉토리에 argv[2]파일이 있는지를 확인하는 프로그램
argv[1] 디렉토리의 모든 항목들의 이름(d_name)중 argv[2]와 같은 것이 있는지를 확인

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

int find_file(char *dir, char *file);

main(int argc, char *argv[])
{
   if (find_file(argv[1], argv[2]))   /* argv[1] 디렉토리에 argv[2] 파일이 있으면 */
      printf("found %s\n", argv[2]);
   else                         /* 없으면 */
      printf("not found %s\n", argv[2]);
   exit(0);
}

/* dir 디렉토리에 file 파일이 있으면 1을 반환하는 함수 */
int find_file(char *dir, char *file)
{
   DIR *dp;   /* 디렉토리 정보에 대한 포인터 */
   struct dirent *dirp;   /* 디렉토리의 한 항목의 정보에 대한 포인터 */

   if((dp=opendir(dir)) == NULL) {   /* dir 디렉토리 열기 */
      perror("opendir failed");
      exit(1);
   }
   /* dp 디렉토리의 항목을 하나씩 읽어 동작 */
   while (dirp=readdir(dp)) {  /* 항목 이름(d_name)이 file과 같으면 1을 반환 */
      if (!strcmp(dirp->d_name, file)) {
         closedir(dp);
         return 1;
      }
   }
   closedir(dp);   /* dp 디렉토리 닫기 */
   return 0;   /* 발견하지 못하면 0을 반환 */
}

---------------------------------------------------------------------------------------------------
현재 작업 디렉토리의 모든 항목들의 이름을 출력하고 rewinddir에 의해 첫번째 항목으로 복귀하고
다시 모든 항목의 이름을 출력한다

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

main()
{
   DIR *dp;
   struct dirent *dirp;

   if((dp=opendir(".")) == NULL) {   /* 현재 디렉토리 열기 */
      perror("opendir failed");
      exit(1);
   }
   /* 디렉토리의 항목들을 읽어서 이름을 출력 */
   while (dirp=readdir(dp)) {
      printf("%s ", dirp->d_name);
   }
   printf("\n");

   rewinddir(dp);   /* 디렉토리 포인터를 첫 번째 항목으로 되돌림 */
   while (dirp=readdir(dp)) {
      printf("%s ", dirp->d_name);
   }
   printf("\n");

   closedir(dp);   /* dp 디렉토리 닫기 */
   exit(0);
}

---------------------------------------------------------------------------------------------------
디렉토리 이름을 dir에 저장하는 데 지정한 디렉토리가 없으면 "."을 저장한다. 그리고 opendir 함수에
의해 dir 디렉토리를 열고 readdir 함수에 의해 디렉토리의 각 항목들에 대한 정보를 이름에 출력한다

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

main(int argc, char *argv[])
{
   DIR *dp;
   struct dirent *dirp;
   char *dir;

   /* 명령 라인의 인수가 1개라면 현재 작업 디렉토리에 대해 동작 */
   if (argc == 1)
      dir = ".";
   /* 그렇지 않으면 argv[1] 디렉토리에 대해 동작 */
   else
      dir = argv[1];
   if((dp=opendir(dir)) == NULL) {   /* dir 디렉토리 열기 */
      perror("opendir failed");
      exit(1);
   }
   /* dp  디렉토리의 모든 항목들에 대한 이름을 출력.
     단, “.”으로 시작되는 항목에 대한 이름은 출력하지 않음 */
   while (dirp=readdir(dp)) {
      if (strncmp(dirp->d_name, ".", 1))
         printf("%s ", dirp->d_name);
   }
   printf("\n");
   closedir(dp);   /* dp 디렉토리 닫기 */
   exit(0);
}

---------------------------------------------------------------------------------------------------
파일형식,파일의 접근권한 ,링크 수, 최종변경시간,파일크기, 파일 내용 파일 이름  --> lstat이용
파일 소유자 --> lstat, getpwuid 이용
와 그룹의 이름 --> lstat, getgrgid 이용
등 다양한 정보를 출력하도록 하는 예제

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#define MAX 512

main(int argc, char *argv[])
{
   DIR *dp;
   struct dirent *dirp;
   char *dir;
   char filename[MAX];
   char list[MAX];
   char buf[MAX];
   struct stat st;
   int index;
   int i;

   /* 명령라인 인수가 1개라면 현재 작업 디렉토리에 대해 동작 */
   if (argc == 1)
      dir = ".";
   /* 그렇지 않으면 argv[1] 디렉토리에 대해 동작 */
   else
      dir = argv[1];
   if((dp=opendir(dir)) == NULL) {   /* dir 디렉토리 열기 */
      perror("opendir failed");
      exit(1);
   }

   while (dirp=readdir(dp)) {   /* dp 디렉토리의 모든 항목들에 대해 처리 */
      index = 0;
      if (!strncmp(dirp->d_name, ".", 1))   /* “.”으로 시작되는 항목은 처리하지 않음 */
         continue;
      sprintf(filename, "%s/%s", dir, dirp->d_name);
      if (lstat(filename, &st) == -1) {   /* filename에 대한 정보를 st에 저장 */
         perror("stat failed");
         exit(1);
      }
      /* 파일 형식을 알아내서 정규 파일은 ‘-’를, 디렉토리는 ‘d’를,
         FIFO 파일은 ‘p’를, 그리고 링크는 ‘l’을 list[0]에 저장 */
      switch (st.st_mode & S_IFMT) {
         case S_IFREG :
            list[index++] = '-';
            break;
         case S_IFDIR :
            list[index++] = 'd';
            break;
         case S_IFIFO :
            list[index++] = 'p';
            break;
         case S_IFLNK :
            list[index++] = 'l';
      }
      /* 파일 접근 권한 알아내기 */
      for (i=0; i<3; i++) {
         if (st.st_mode & (S_IREAD >> i*3)) /*S_IREAD = S_IRUSR(0400)
            list[index++] = 'r';
         else
            list[index++] = '-';
         if (st.st_mode & (S_IWRITE >> i*3)) /*S_IWRITE = S_IWUSR(0200)
            list[index++] = 'w';
         else
            list[index++] = '-';
         if (st.st_mode & (S_IEXEC >> i*3)) /*S_IEXEC = S_IXUSR(0100)
            list[index++] = 'x';
         else
            list[index++] = '-';
      }
      list[index] = '\0';   /* 문자열의 마지막을 의미 */
      /* 링크 수, 파일 소유자 */
      printf("%s%5d %s ", list, st.st_nlink, (getpwuid(st.st_uid))->pw_name);
      /* 파일 그룹 이름, 파일 크기 */
      printf("%s%9d ", (getgrgid(st.st_gid))->gr_name, st.st_size);
      /* 파일 내용 최종 변경 시간 */
      sprintf(buf, "%s", ctime(&st.st_mtime));
      /* 파일에 대한 최종 수정 시간을 ctime(&st.st_mtime)로 출력하면 개행이
        자동적으로 이루어지므로 개행이 일어나지 않도록 ’\n' 위치에 ‘\0’을 넣음 */
      buf[strlen(buf)-1] = '\0';
      printf("%s %s\n", buf, dirp->d_name);   /* 파일 이름 */
   }
   closedir(dp);
   exit(0);
}

---------------------------------------------------------------------------------------------------
link와 unlink를 이용하여 파일 이름을 argv[1]에서 argv[2]로 변경하는 프로그램
하드링크

#include <stdio.h>
#include <unistd.h>

main(int argc, char *argv[])
{
   /* argv[1]에 대한 링크 argv[2]를 생성하여 argv[1]과 argv[2]는 같은 파일이 됨 */
   if (link(argv[1], argv[2]) == -1) { /* 정규파일에서만 동작 심볼릭링크는 디렉토리도 가능*/
      perror("link failed");
      exit(1);
   }
   /* argv[1] 링크를 삭제하나 argv[2]는 지워지지 않음.
     결국 argv[1]이 argv[2]로 이름이 변경 */
   if (unlink(argv[1]) == -1) {
      perror("unlink failed");
      unlink(argv[2]);
      exit(1);
   }
   printf("move %s to %s\n", argv[1], argv[2]);
   exit(0);
}

---------------------------------------------------------------------------------------------------
하드링크는 동일한 inode를 이용하는 반면 심볼릭링크는 각자의 inode를 가지고 있느나 파일은 같은것이다
symlink를 이용하여 심볼릭 링크를 생성하는 프로그램 디렉토리 dir1에 대해 심볼릭 링크 dir1을 생성한
예제

#include <stdio.h>
#include <unistd.h>

main(int argc, char *argv[])
{
   if (symlink(argv[1], argv[2]) == -1) {   /* argv[1]에 대한 심볼릭 링크 argv[2]를 생성 */
      perror("symlink failed");
      exit(1);
   }
   printf("link %s to %s\n", argv[1], argv[2]);
   exit(0);
}

---------------------------------------------------------------------------------------------------
stat는 심볼릭 링크가 가리키는 파일에 대한 정보를 반환하는 반면 lstat는 링크 자체에 대한 정보를 반환
을 확인하는 예제

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

main(int argc, char *argv[])
{
   struct stat st1, st2;

   /* argv[1]에 대한 심볼릭 링크 argv[2]를 생성 */
   if (symlink(argv[1], argv[2]) == -1) {
      perror("symlink failed");
      exit(1);
   }
   /* stat를 이용해서 심볼릭 링크 argv[2]에 대한 정보를 st1에 저장.
     심볼릭 링크가 가리키는 파일에 대한 정보가 저장 */
   if (stat(argv[2], &st1) == -1) {
      perror("stat failed");
      exit(1);
   }
   /* lstat를 이용해서 심볼릭 링크 argv[2]에 대한 정보를 st2에 저장.
    심볼릭 링크 자체에 대한 정보가 저장 */
   if (lstat(argv[2], &st2) == -1) {
      perror("stat failed");
      exit(1);
   }
   printf("%ld bytes : %ld bytes\n", st1.st_size, st2.st_size);
   exit(0);
}

---------------------------------------------------------------------------------------------------
파일 또는 디렉토리 삭제 예제

#include <stdio.h>
#include <unistd.h>

main(int argc, char *argv[])
{
   if (remove(argv[1]) == -1) {   /* argv[1]을 삭제 */
      perror("remove failed");
      exit(1);
   }
   printf("remove %s\n", argv[1]);
   exit(0);
}

---------------------------------------------------------------------------------------------------
argv[1]파일 또는 디렉토리의 이름을 argv[2]로 변경하는 프로그램

#include <stdio.h>

main(int argc, char *argv[])
{
   if (rename(argv[1], argv[2]) == -1) {   /* argv[1]을 argv[2]로 이름을 변경 */
      perror("rename failed");
      exit(1);
   }
   printf("rename %s to %s\n", argv[1], argv[2]);
   exit(0);
}

---------------------------------------------------------------------------------------------------

#include <sys/types.h>
#include <sys/stat.h>

main()
{
   /* jkim의 접근 권한을 0644로 변경.
     소유자는 읽기, 쓰기 권한, 그룹과 기타 사용자들은 읽기 권한이 부여 */
   if (chmod("jkim", 0644) == -1)
      perror("chmod failed");
   /* kang의 접근 권한을 변경.
     소유자는 읽기, 쓰기 권한, 그룹과 기타 사용자들은 읽기 권한이 부여 */
   if (chmod("kang", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
      perror("chmod failed");
   exit(0);
}


---------------------------------------------------------------------------------------------------
argv[2]파일의 소유자와 그룹으 argv[1] 파일의 소유자와 그룹으로 변경하는 프로그램

#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>

main(int argc, char *argv[])
{
   struct stat st;

   if (stat(argv[1], &st) == -1) {   /* argv[1] 파일에 대한 정보가 st에 저장 */
      perror("stat failed");
      exit(1);
   }
   /* argv[2]의 소유자와 그룹을 st.st_uid와 st.st_gid로 변경 */
   if (chown(argv[2], st.st_uid, st.st_gid) == -1) { /*2,3번째 인수가 -1인경우 각 인수는 변경 안됨*/
      perror("chown failed");
      exit(1);
   }
   exit(0);
}

---------------------------------------------------------------------------------------------------
루트 디렉토리 변경

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

main()
{
   /* 루트 디렉토리를 /home/jkim/book/linux/chap22로 변경 */
   if(chroot("/home/jkim/book/linux/chap22") == -1) {
      perror("chroot failed");
      exit(1);
   }
   if(chdir("/") == -1) {   /* 루트 디렉토리로 이동 */
      perror("chdir failed");
      exit(1);
   }
   if(mkdir("rootsub", 0777) == -1) {   /* rootsub 디렉토리를 생성 */
      perror("mkdir failed");
      exit(1);
   }
   exit(0);
}

Posted by 몰라욧