'filesystem'에 해당되는 글 1건

Linux 에서 동적 착탈되는 파일시스템을 검출하는 예제입니다.
개념적인 이해만 되면 USB drive 나 Floppy, CDROM 등을 검출하는 프로그램을 작성할수 있겠지요

현재 이 예제는 일단 USB drive 만 인식하도록 되어 있습니다. (정확히는 "*/sd*" 장치를 검출하게 작성되었습니다.

mzdetectfs.c
코드:
/*
  Copyright (C) Information Equipment co.,LTD
  All rights reserved.
  Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
  CVSTAG="$Id$"
*/

#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h>

#include "partition.h"

#define __def_detectfs_debug__                                       (1)

static volatile int g_mz_detectfs_break = 0;
static volatile int g_mz_detectfs_verify = 0;

static void mz_detectfs_signal(int s_signal)
{
 switch(s_signal)
 {
  case SIGINT: case SIGTERM: case SIGQUIT: g_mz_detectfs_break = 1; (void)signal(s_signal, mz_detectfs_signal); break;
  case SIGSEGV: case SIGFPE: (void)raise(s_signal); exit(1); break;
  default: if(g_mz_detectfs_verify != 0)(void)fprintf(stderr, "detectfs: [ERROR] unknown signal ! (signal=%08XH)\n", s_signal); break;
 }
}

static int (mz_detectfs_filter)(struct ts_mz_partition *s_partition)
{
 if((s_partition->name == ((char *)0)) || (s_partition->name_size < ((size_t)3)))return(0);
 if((s_partition->name[0] != 's') || (s_partition->name[1] != 'd'))return(0);
 return(1);
}

/* ------------------- */
static int (mz_detectfs_do_work)(int s_valid, struct ts_mz_partition *s_partition, const char *s_entry)
{
 int s_result = 0;
 if(s_valid != 0)
 {
  if(g_mz_detectfs_verify != 0)
  {
   unsigned char s_buffer[ 4 << 10 ];
   if(s_partition->level[1] == 0u)(void)sprintf((char *)(&s_buffer[0]), "%s/%u", s_entry, s_partition->level[0]);
   else (void)sprintf((char *)(&s_buffer[0]), "%s/%u/%u", s_entry, s_partition->level[0], s_partition->level[1]);
   (void)fprintf(stdout, "entry[%s]\n", (char *)(&s_buffer[0]));
  }
 }
 return(s_result);
}
/* ------------------- */

int (main)(int s_argc, char **s_argv)
{
 int s_result = 0, s_option, s_help = 0, s_interval = 1, s_check;
 const char *s_entry = (char *)0;
 struct ts_mz_partition *s_partition, *s_trace;
 (void)signal(SIGINT, mz_detectfs_signal); (void)signal(SIGTERM, mz_detectfs_signal); (void)signal(SIGQUIT, mz_detectfs_signal);
 (void)signal(SIGSEGV, mz_detectfs_signal); (void)signal(SIGFPE, mz_detectfs_signal);
 while((s_option = getopt(s_argc, s_argv, "hve:i:")) != (-1))
 {
  switch(s_option)
  {
   case 'h': s_help = 1;
   case 'v': g_mz_detectfs_verify = 1; break;
   case 'e': s_entry = optarg; break;
   case 'i': if(sscanf(optarg, "%d", &s_interval) != 1)s_interval = 1; break;
   default: break;
  }
 }
 if(s_entry == ((char *)0))s_entry = "/mnt/usb";
 if(g_mz_detectfs_verify != 0)(void)fprintf(stdout, "mzdetectfs v0.0.1 build 0 (%s %s) by <minzkn@infoeq.com>\n\n", __DATE__, __TIME__);
 if(s_help != 0)
 {
  (void)fprintf(stdout,
   "Usage: %s [-h] [-e <mount entry>] [-i <interval>] [-v]\n"
   "Options:\n"
   "\t-h               : display this help and exit\n"
   "\t-e <mount entry> : mount entry\n"
   "\t-i <interval>    : check interval (sec)\n"
   "\t-v               : be verbose\n",
   s_argv[0]);
 }
 else
 {
  do
  {
   s_trace = s_partition = mz_get_partition_list("/proc/partitions");
   if(s_partition != ((struct ts_mz_partition *)0))
   {
    while(s_trace != ((struct ts_mz_partition *)0))
    {
     s_check = mz_detectfs_filter(s_trace);
     
     (void)mz_detectfs_do_work(s_check, s_trace, s_entry);
     
     if(g_mz_detectfs_verify != 0)
     {
      (void)fprintf(stdout, "\tmajor=%3u, minor=%3u, blocks=%11llu, name_size=%2u, ",
      s_trace->major, s_trace->minor, s_trace->blocks, (unsigned int)s_trace->name_size);
      if(s_check != 0)(void)fprintf(stdout, "name=\"\x1b[1;33m%s\x1b[0m\"\n", s_trace->name);
      else (void)fprintf(stdout, "name=\"%s\"\n", s_trace->name);
      if(s_trace->next == ((struct ts_mz_partition *)0))(void)fputs("\n", stdout);
     }
     s_trace = s_trace->next;
    }
    (void)mz_free_partition_list(s_partition);
   }
   if(s_interval > 0)(void)sleep(s_interval);
  }while(g_mz_detectfs_break == 0);
 }
 if(g_mz_detectfs_verify != 0)(void)fputs("\nEnd of detectfs.\n", stdout);
 return(s_result);
}

/* vim: set expandtab: */
/* End of source */


partition.c
코드:
/*
  Copyright (C) Information Equipment co.,LTD
  All rights reserved.
  Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
  CVSTAG="$Id$"
*/

#if !defined(__def_detectfs_source_partition_c__)
#define __def_detectfs_source_partition_c__

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include "partition.h"

#define __def_detectfs_buffer_size__                                 (4 << 10)

size_t (mz_get_word_sep)(const char *s_sep, char **s_sep_string, void *s_data, size_t s_size);
struct ts_mz_partition * (mz_new_partition)(void);
struct ts_mz_partition * (mz_free_partition)(struct ts_mz_partition *s_partition);
struct ts_mz_partition * (mz_parse_proc_partition_line)(const char *s_line);
struct ts_mz_partition * (mz_get_partition_list)(const char *s_proc_path);
struct ts_mz_partition * (mz_free_partition_list)(struct ts_mz_partition *s_partition);

size_t (mz_get_word_sep)(const char *s_sep, char **s_sep_string, void *s_data, size_t s_size)
{
 size_t s_result;
 const char *s_left, *s_right, *s_sep_ptr;
 char *s_string = *(s_sep_string);
 while((*(s_string) == ' ') || (*(s_string) == '\t'))s_string++;
 s_left = s_right = s_string;
 while(*(s_string) != '\0')
 {
  s_sep_ptr = s_sep; while((*(s_string) != *(s_sep_ptr)) && (*(s_sep_ptr) != '\0'))s_sep_ptr++;
  if(*(s_string) == *(s_sep_ptr))break;
  if(*(s_string) != ' ')s_right = ++s_string;
  else s_string++;
 }
 s_result = (size_t)(s_right - s_left);
 (void)memcpy(s_data, s_left, (s_result > (s_size - ((size_t)1))) ? (s_size - ((size_t)1)) : s_result);
 *(((char *)s_data) + s_result) = '\0';
 *(s_sep_string) = s_string;
 return(s_result);
}

struct ts_mz_partition * (mz_new_partition)(void)
{
 struct ts_mz_partition *s_partition = (struct ts_mz_partition *)malloc((size_t)sizeof(struct ts_mz_partition));
 if(s_partition != ((struct ts_mz_partition *)0))(void)memset((void *)s_partition, 0, (size_t)sizeof(struct ts_mz_partition));
 return(s_partition);
}

struct ts_mz_partition * (mz_free_partition)(struct ts_mz_partition *s_partition)
{
 if(s_partition != ((struct ts_mz_partition *)0))
 {
  if(s_partition->name != ((char *)0))free((void *)s_partition->name);
  free((void *)s_partition);
 }
 return((struct ts_mz_partition *)0);
}

struct ts_mz_partition * (mz_parse_proc_partition_line)(const char *s_line)
{
 struct ts_mz_partition *s_new = (struct ts_mz_partition *)0;
 const char *s_sep_string = s_line;
 unsigned char s_buffer[ __def_detectfs_buffer_size__ ];
 int s_word_count = 0;
 unsigned int s_major, s_minor;
 unsigned long long s_blocks;
 char *s_name;
 size_t s_size;
 do
 {
  s_size = mz_get_word_sep(" \t", (char **)(&s_sep_string), (void *)(&s_buffer[0]), (size_t)sizeof(s_buffer));
  if(*(s_sep_string) != '\0')s_sep_string++;
  if(s_size <= ((size_t)0))break;
  if(s_word_count == 0){ /* major */ if(sscanf((char *)(&s_buffer[0]), "%u", &s_major) != 1)break; }
  else if(s_word_count == 1){ /* minor */ if(sscanf((char *)(&s_buffer[0]), "%u", &s_minor) != 1)break; }
  else if(s_word_count == 2){ /* blocks */ if(sscanf((char *)(&s_buffer[0]), "%llu", &s_blocks) != 1)break; }
  else
  { /* name */
   s_name = (char *)malloc(strlen((char *)(&s_buffer[0])) + ((size_t)1));
   if(s_name == ((char *)0))break;
   (void)strcpy(s_name, (char *)(&s_buffer[0]));
   s_new = mz_new_partition();
   if(s_new == ((struct ts_mz_partition *)0))free((void *)s_name);
   else
   {
    s_new->major = s_major;
    s_new->minor = s_minor;
    s_new->level[0] = s_minor >> 4;
    s_new->level[1] = s_minor & 0x0fu;
    s_new->blocks = s_blocks;
    s_new->name = s_name;
    s_new->name_size = s_size;
   }
   break;
  }
  s_word_count++;
 }while(*(s_sep_string) != '\0');
 return(s_new);
}

struct ts_mz_partition * (mz_get_partition_list)(const char *s_proc_path)
{
 struct ts_mz_partition *s_partition = (struct ts_mz_partition *)0, *s_last = (struct ts_mz_partition *)0, *s_new;
 int s_handle = open(s_proc_path, O_RDONLY);
 unsigned char s_buffer[2][ __def_detectfs_buffer_size__ ];
 ssize_t s_read_bytes;
 const char *s_sep_string = (char *)(&s_buffer[0][0]);
 if(s_handle != (-1))
 {
  s_read_bytes = read(s_handle, (void *)(&s_buffer[0][0]), (size_t)(sizeof(s_buffer[0]) - 1));
  if(s_read_bytes > ((ssize_t)0))
  {
   s_buffer[0][s_read_bytes] = (unsigned char)'\0';
   do
   {
    (void)mz_get_word_sep("\n\r", (char **)(&s_sep_string), (void *)(&s_buffer[1][0]), (size_t)sizeof(s_buffer[1]));
    s_new = mz_parse_proc_partition_line((char *)(&s_buffer[1][0]));
    if(s_new != ((struct ts_mz_partition *)0))
    { /* add */
     if(s_last != ((struct ts_mz_partition *)0))s_last->next = s_new;
     else s_partition = s_new;
     s_last = s_new;
    }
    if(*(s_sep_string) != '\0')s_sep_string++;
   }while(*(s_sep_string) != '\0');
  }
  (void)close(s_handle);
 }
 return(s_partition);
}

struct ts_mz_partition * (mz_free_partition_list)(struct ts_mz_partition *s_partition)
{
 while(s_partition != ((struct ts_mz_partition *)0)){ struct ts_mz_partition *s_prev = s_partition; s_partition = s_partition->next; (void)mz_free_partition(s_prev); }
 return((struct ts_mz_partition *)0);
}

#endif

/* vim: set expandtab: */
/* End of source */


partition.h
코드:
/*
  Copyright (C) Information Equipment co.,LTD
  All rights reserved.
  Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
  CVSTAG="$Id$"
*/

#if !defined(__def_detectfs_source_partition_h__)
#define __def_detectfs_source_partition_h__

struct ts_mz_partition
{
 struct ts_mz_partition *next;
 unsigned int major, minor, level[2];
 unsigned long long blocks;
 char *name;
 size_t name_size;
};

#if !defined(__def_detectfs_source_partition_c__)
extern size_t (mz_get_word_sep)(const char *s_sep, char **s_sep_string, void *s_data, size_t s_size);
extern struct ts_mz_partition * (mz_new_partition)(void);
extern struct ts_mz_partition * (mz_free_partition)(struct ts_mz_partition *s_partition);
extern struct ts_mz_partition * (mz_parse_proc_partition_line)(const char *s_line);
extern struct ts_mz_partition * (mz_get_partition_list)(const char *s_proc_path);
extern struct ts_mz_partition * (mz_free_partition_list)(struct ts_mz_partition *s_partition);
#endif

#endif

/* vim: set expandtab: */
/* End of source */


Makefile
코드:
# Copyright (C) Information Equipment co.,LTD
# All rights reserved.
# Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
# CVSTAG="$Id$"

CROSS_COMPILE                ?=#

CC                           := $(CROSS_COMPILE)gcc#
RM                           := rm -f#
STRIP                        := $(CROSS_COMPILE)strip#

THIS_NAME                    := mzdetectfs#

CFLAGS                       := -Os -pipe -ansi#
CFLAGS                       += -Wall -Werror#
CFLAGS                       += -fomit-frame-pointer#
CFLAGS                       += -I.#

LDFLAGS                      := -s#

TARGET                       := $(THIS_NAME)#
OBJECTS                      := $(THIS_NAME).o#
OBJECTS                      += partition.o#

.PHONY: all clean

all: $(TARGET) ; $(STRIP) --remove-section=.comment --remove-section=.note $(^)
clean: ; $(RM) *.o $(TARGET)
$(TARGET): $(OBJECTS) ; $(CC) $(LDFLAGS) -o $(@) $(^)
$(OBJECTS): Makefile
%.o: %.c ; $(CC) $(CFLAGS) -c -o $(@) $(<)

# End of Makefile
크리에이티브 커먼즈 라이센스
Creative Commons License
Posted by minzkn

트랙백 주소 :: http://blog.minzkn.com/trackback/173

댓글을 달아 주세요