----------------------------------------------------------------------------------------------------------------------------------------------------------
/* * ===================================================================================== * * Filename: seer_trace.c * Description: traslating seer format traces to the format can be used in object oriented file system * Version: 1.0 * Created: 07/05/2012 12:17:11 AM * Revision: none * Compiler: gcc * Author: Si Ma * * ===================================================================================== */ #include <string.h> #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include "list.h" #define MAX_CHARS 10000 // max number of chars of one line #define MAX_FILES 20000 //max number of files used at the same time in one trace #define SYSCALL_NUM 7 #define SYSCALL_NUM_MAC 5 /** * file_node * @ oid: object id of this file, from the value of time33(pathname) * @ cur_offset: current read/write offset * fd will be the index of file_node array... */ struct file_node{ unsigned long oid; unsigned long cur_offset; }; struct file_node File_hstb[MAX_FILES]; struct user{ int usr_id; char cur_path[1000]; struct list_head list; }; /** * system call list that we care about in the original trace file */ char *SYS_CALL[SYSCALL_NUM]={ "open\0", "chdir\0", "read\0", "write\0", "lstat\0", "stat\0", "close\0" //0--5 }; /** * system call list that we care about in the original trace file */ char *SYS_CALL_MAC[SYSCALL_NUM_MAC]={ "oread\0", "owrite\0", "ogattr\0", "osattr\0", "oflush\0" }; /** * type list of the lines in the trace file */ char *LINE_TYPE[3]={ "UID\0", //we only need this type and the other two will be ignored "TIMESTAMP\0", "RESTART\0" }; /** * path2oid - mapping pathname to object id: time33 hashing */ unsigned long path2oid(char const *pathname, int len) { unsigned long hash = 0; int i ; for (i=0; i < len; i++) { hash = ((hash <<5) + hash) + (unsigned long) pathname[i]; } return hash; } /** * type_of_op - check and return the specific index number according to SYS_CALL array * @op: operation string abstracted from the line buffer */ int type_of_op(char *op) { int i=0; for(i=0; i<SYSCALL_NUM;i++){ //printf("\nloop for the %d time", i+1); if(strcmp(op,SYS_CALL[i])==0) return i; } return -1; } /** * extract_no_str - to extract the NO.(no+1) item from this line: l_buf * @l_buf: line buffer * @ no: the number of item in l_buf * @ str: to save the NO.no item in l_buf */ int extract_no_str(char *l_buf, int no, char* str) { int l_len=strlen(l_buf); int i=0, j=0, k=0; if(!str) return 1; for(i=0; i< l_len; i++){ if(l_buf[i]==32){ //space: 32... j++; i=i+1; if(j==no-1) break; } } while(l_buf[i]!=32) str[k++]=l_buf[i++]; str[k]='\0'; return 0; } /** * extract_op - to extract the operation item from this line: l_buf * @l_buf: line buffer * @ op: to save the operation item in l_buf */ int extract_op(char *l_buf, char* op) { int l_len=strlen(l_buf); int i=0, j=0, k=0; if(!op) return 1; for(i=0; i< l_len; i++){ if(l_buf[i]==32){ //space: 32... j++; i=i+1; if(j==8) break; } } while(l_buf[i]!='(') op[k++]=l_buf[i++]; op[k]='\0'; return 0; } /** * extract_path - to extract the path item from this line: l_buf * @l_buf: line buffer * @ op: to save the path item in l_buf */ int extract_path(char *l_buf, char* path) { int l_len=strlen(l_buf); int i=0, k=0; if(!path) return 1; while(l_buf[i]!=34) //34 is ascii of ' " ' i++; i++; while(l_buf[i]!=34) path[k++]=l_buf[i++]; path[k]='\0'; //printf("\nIn extract_path and path is: %s", path); return 0; } /** * extract_last_item - to extract the last item: return value from this line: l_buf * @l_buf: line buffer * @ rt: to save the last item in l_buf */ int extract_last_item(char *l_buf, char* rt) { int k=0, l_len=strlen(l_buf); int off_set=l_len-3; while(l_buf[off_set]!='=') off_set--; //printf("\noff_set is: %d", off_set); k=0; off_set+=2; while((l_buf[off_set]<58)&&(l_buf[off_set]>44)&&(off_set < l_len)) rt[k++]= l_buf[off_set++]; rt[k]='\0'; //printf("\nIn extract_last_item and fd is |%s|", rt); return 0; } struct user * user_lookup(struct list_head *user_list, int uid) { struct list_head *pos; struct user *tmp; list_for_each(pos, user_list){ tmp = list_entry(pos, struct user, list); //printf("\nuserid is :%d pathname is: %s", tmp->usr_id, tmp->cur_path); } list_for_each(pos, user_list){ tmp = list_entry(pos, struct user, list); if(tmp->usr_id==uid) return tmp; } return NULL; } int free_userlist(struct list_head *user_list) { printf("\nuser_lookup is called ..."); struct list_head *pos; struct user *tmp; list_for_each(pos, user_list){ tmp = list_entry(pos, struct user, list); list_del(&(tmp->list)); free(tmp); } return 0; } int extract_rw_fd(char *l_buf, char *s_fd) { int i=0, j=0; for(i=0;i<strlen(l_buf);i++) if(l_buf[i]=='(') break; i++; while(l_buf[i]!=',') s_fd[j++]=l_buf[i++]; s_fd[j]='\0'; return 0; } /** * line_process - refine the operation and parameters according to the specific content of this line * @ l_buf: buffer contains this line * @ o_fs: object file stream handler * file obj_trace.txt will contai the final trace result */ int line_process(char *l_buf, FILE *o_fs, struct list_head *user_list) { int op_no=100; char l_type[10], op[10]; extract_no_str(l_buf, 2, l_type); if(-1==strcmp(l_type,LINE_TYPE[0])) //we only need type of "UID" and ignore "RESTART" and "TIMESTAMP" return 0; extract_op(l_buf, op); //operation type op_no = type_of_op(op); switch(op_no){ case 0: //printf("\nhandle line open..."); handle_line_open(l_buf, user_list); break; case 1: //printf("\nhandle line chdir..."); handle_line_chdir(l_buf, user_list); break; case 2: //printf("\nhandle line read..."); handle_line_read(l_buf,o_fs); break; case 3: //printf("\nhandle line write..."); handle_line_write(l_buf, o_fs); break; case 4: case 5: //printf("\nhandle line stat..."); handle_line_path_stat(l_buf, user_list, o_fs); break; case 6: handle_line_close(l_buf,o_fs); break; default: break; } //printf("\nOne line is processed..."); return 0; } int main(int argc, char *argv[]) { if(argc < 2){ printf("\nPlease make sure that you have input your trace file!!\n"); return 0; }else{ printf("\nTrace file is: %s\n", argv[1]); } char line_buf[MAX_CHARS]; int i=0; FILE * fs, *ofs; struct list_head *user_list; //=&usr_list; LIST_HEAD(ulist); user_list=&ulist; INIT_LIST_HEAD(user_list); //define and init the user list fs = fopen(argv[1], "r+"); ofs = fopen("obj_trace.txt", "a+"); for(i=0;i<MAX_FILES;i++){ File_hstb[i].cur_offset = 0; File_hstb[i].oid =0; } i=0; if(fs && ofs){ while(fgets(line_buf, MAX_CHARS, fs) > 0){ //get one line from the file... //if(i>220000) // break; i++; line_process(line_buf, ofs, user_list); } } //free_userlist(); printf("\nThe number of last line is:%d \n", i); fclose(fs); fclose(ofs); return 0; } /** * handle_line_open - process a line of open trace * @ l_buf: buffer contains this line */ int handle_line_open(char *l_buf, struct list_head *user_list) { int fd=0; char pathname[500], s_fd[150], tmppath[500]; struct user *cur_user=NULL; int i=0, j=0; int usr_id; char uid[10]; extract_last_item(l_buf, s_fd); fd=atoi(s_fd); //printf("\nfd:%d...",fd); if(fd<0||fd>20000) //if open failed , just ignore this line return 0; extract_path(l_buf,pathname); switch(pathname[0]){ case '.': //printf("\nopen case . .."); extract_no_str(l_buf, 3, uid); usr_id=atoi(uid); cur_user=user_lookup(user_list, usr_id); if(cur_user==NULL){ cur_user=(struct user*)malloc(sizeof(struct user)); cur_user->cur_path[0]='/'; cur_user->cur_path[1]='\0'; //default current path : "/" cur_user->usr_id=usr_id; list_add(&(cur_user->list), user_list); //add this new user to the list strcpy(pathname,cur_user->cur_path); }else{ if((strlen(pathname)>=2)&&pathname[1]=='.'){ strcpy(tmppath,cur_user->cur_path); for(i=strlen(tmppath);i>0; i--) //here we assume ../../../ will not emerge... if(tmppath[i]=='/'){ tmppath[i]='\0'; break; } for(i=0; i<strlen(pathname)-2;i++)//delete .. from the head pathname[i]=pathname[i+2]; strcat(tmppath, pathname); strcpy(pathname,tmppath); //here the dir of the file is ok... }else if((strlen(pathname)>=2)&&pathname[1]=='/'){ strcpy(tmppath,cur_user->cur_path); for(i=0; i<strlen(pathname);i++) pathname[i]=pathname[i+1]; strcat(tmppath, pathname); strcpy(pathname,tmppath); }else{ //case the file type like .config strcpy(tmppath,cur_user->cur_path); j=strlen(pathname); if(pathname[j-1]!='/'){ pathname[j]='/'; pathname[j+1]='\0'; } strcat(tmppath, pathname); strcpy(pathname,tmppath); } } break; case '/': //printf("\nopen case / .."); break; default: //printf("\nopen case default .."); extract_no_str(l_buf, 3, uid); usr_id=atoi(uid); cur_user=user_lookup(user_list, usr_id); if(cur_user==NULL){ cur_user=(struct user*)malloc(sizeof(struct user)); cur_user->cur_path[0]='/'; cur_user->cur_path[1]='\0'; //default current path : "/" cur_user->usr_id=usr_id; list_add(&(cur_user->list), user_list); //add this new user to the list strcpy(pathname,cur_user->cur_path); }else{ strcpy(tmppath,cur_user->cur_path); j=strlen(pathname); if(pathname[j-1]!='/'){ pathname[j]='/'; pathname[j+1]='\0'; } strcat(tmppath, pathname); strcpy(pathname,tmppath); //here the dir of the file is ok... } break; } //printf("\npathname is: %s", pathname); File_hstb[fd].cur_offset= 0; File_hstb[fd].oid=path2oid(pathname, strlen(pathname)); return 0; } int handle_line_chdir(char *l_buf, struct list_head *user_list) { int fd=0; char pathname[5000], s_fd[15], tmppath[5000]; struct user *cur_user=NULL; int i=0, j=0; int usr_id; char uid[10]; extract_last_item(l_buf, s_fd); fd=atoi(s_fd); if(fd<0||fd>20000) //if open failed , just ignore this line return 0; extract_path(l_buf,pathname); extract_no_str(l_buf, 3, uid); usr_id=atoi(uid); cur_user=user_lookup(user_list, usr_id); if(cur_user==NULL){ cur_user=(struct user*)malloc(sizeof(struct user)); cur_user->cur_path[0]='/'; cur_user->cur_path[1]='\0'; cur_user->usr_id=usr_id; list_add(&(cur_user->list), user_list); //add this new user to the list strcpy(cur_user->cur_path, pathname); }else{ //printf("\nOrignal cur-path is:%s and pathname is: %s", cur_user->cur_path, pathname); switch(pathname[0]){ case '.': //printf("\nEntering . dir..."); if((strlen(pathname)>=2)&&(pathname[1]=='.')){ strcpy(tmppath,cur_user->cur_path); //printf("\nAfter strcpy .. dir..."); j=0; for(i=strlen(tmppath);i>0; i--){ //cd .. here we assume ../../../ will not emerge... if(tmppath[i]=='/'){ j++; if(j==2){ tmppath[i]='\0'; break; } } //printf("\ni value is: %d", i); } for(i=0; i<strlen(pathname);i++)//delete .. from the head pathname[i]=pathname[i+2]; strcat(tmppath, pathname); strcpy(cur_user->cur_path,tmppath); }else{ strcpy(tmppath,cur_user->cur_path); for(i=0; i<strlen(pathname);i++) pathname[i]=pathname[i+1]; strcat(tmppath, pathname); strcpy(cur_user->cur_path,tmppath); //here the dir of the file is ok... } break; case '/': if(cur_user->cur_path[strlen(cur_user->cur_path)-1]=='/'){ for(i=0; i<strlen(pathname)-1;i++) tmppath[i]=pathname[i+1]; tmppath[i]='\0'; strcat(cur_user->cur_path,tmppath); }else strcat(cur_user->cur_path, pathname); strcpy(cur_user->cur_path,pathname); break; default: // directly a name string.... if(cur_user->cur_path[strlen(cur_user->cur_path)-1]!='/'){ tmppath[0]='/'; for(i=0; i<strlen(pathname);i++) tmppath[i+1]=pathname[i]; tmppath[i+2]='\0'; strcat(cur_user->cur_path,tmppath); }else strcat(cur_user->cur_path, pathname); break; } } //printf("\nAfter chdir: cur-path is:%s", cur_user->cur_path); return 0; } int handle_line_read(char *l_buf, FILE * o_fs) { int fd, rcount; char s_fd[15], s_rct[15]; extract_rw_fd(l_buf, s_fd); fd=atoi(s_fd); extract_last_item(l_buf, s_rct); rcount=atoi(s_rct); if(rcount<=0) return 0; if(o_fs) fprintf(o_fs,"0 %s %lu %lu %d\n", SYS_CALL_MAC[0], File_hstb[fd].oid, File_hstb[fd].cur_offset, rcount); else printf("\nInvalid file handler..."); File_hstb[fd].cur_offset+=rcount; return 0; } int handle_line_close(char *l_buf, FILE * o_fs) { int fd; char s_fd[15]; extract_rw_fd(l_buf, s_fd); fd=atoi(s_fd); if(o_fs) fprintf(o_fs,"0 %s %lu\n", SYS_CALL_MAC[4], File_hstb[fd].oid); else printf("\nInvalid file handler..."); return 0; } int handle_line_write(char *l_buf, FILE * o_fs) { int fd, count; char s_fd[15], s_ct[15]; extract_rw_fd(l_buf, s_fd); fd=atoi(s_fd); extract_last_item(l_buf, s_ct); count=atoi(s_ct); if(count<=0) return 0; if(o_fs) fprintf(o_fs,"0 %s %lu %lu %d\n", SYS_CALL_MAC[1], File_hstb[fd].oid, File_hstb[fd].cur_offset, count); else printf("\nInvalid file handler..."); File_hstb[fd].cur_offset+=count; return 0; } int handle_line_path_stat(char *l_buf, struct list_head *user_list, FILE * o_fs) { int rtv=0; char pathname[5000], s_rt[15], tmppath[5000]; struct user *cur_user=NULL; int i=0, j=0; int usr_id; char uid[10]; extract_last_item(l_buf, s_rt); rtv=atoi(s_rt); if(rtv<0) //if stat failed , just ignore this line return 0; //printf("\n\n\nin handle line stat and before extract pathname..."); extract_path(l_buf,pathname); switch(pathname[0]){ case '.': //printf("\nIn stat case . ...."); extract_no_str(l_buf, 3, uid); usr_id=atoi(uid); cur_user=user_lookup(user_list, usr_id); if(cur_user==NULL){ cur_user=(struct user*)malloc(sizeof(struct user)); cur_user->cur_path[0]='/'; cur_user->cur_path[1]='\0'; //default current path : "/" cur_user->usr_id=usr_id; list_add(&(cur_user->list), user_list); //add this new user to the list strcpy(pathname,cur_user->cur_path); break; } if((strlen(pathname)>=2)&&pathname[1]=='.'){ //printf("\nEntering .. process..."); strcpy(tmppath,cur_user->cur_path); for(i=strlen(tmppath);i>0; i--) //here we assume ../../../ will not emerge... if(tmppath[i]=='/'){ tmppath[i]='\0'; break; } for(i=0; i<strlen(pathname);i++)//delete .. from the head pathname[i]=pathname[i+2]; strcat(tmppath, pathname); strcpy(pathname,tmppath); //here the dir of the file is ok... }else if((strlen(pathname)>=3)&&pathname[1]=='/'){ strcpy(tmppath,cur_user->cur_path); for(i=0; i<strlen(pathname);i++)//delete .. from the head pathname[i]=pathname[i+1]; strcat(tmppath, pathname); strcpy(pathname,tmppath); }else{ //case the file type .config strcpy(tmppath,cur_user->cur_path); j=strlen(pathname); pathname[j]='/'; pathname[j+1]='\0'; strcat(tmppath, pathname); strcpy(pathname,tmppath); //here the dir of the file is ok... } break; case '/': //printf("\nIn stat case / ...."); break; default: //printf("\nIn stat case default ...."); extract_no_str(l_buf, 3, uid); usr_id=atoi(uid); cur_user=user_lookup(user_list, usr_id); if(cur_user==NULL){ cur_user=(struct user*)malloc(sizeof(struct user)); cur_user->cur_path[0]='/'; cur_user->cur_path[1]='\0'; //default current path : "/" cur_user->usr_id=usr_id; list_add(&(cur_user->list), user_list); //add this new user to the list strcpy(pathname,cur_user->cur_path); }else{ strcpy(tmppath,cur_user->cur_path); j=strlen(pathname); pathname[j]='/'; pathname[j+1]='\0'; strcat(tmppath, pathname); strcpy(pathname,tmppath); //here the dir of the file is ok... } break; } if(o_fs) fprintf(o_fs,"0 %s %lu\n", SYS_CALL_MAC[2], path2oid(pathname, strlen(pathname))); else printf("\nInvalid file handler..."); return 0; }