int getdents(char *path) { char buf[BUF_SIZE]; int total_read = 0; int read = 0; int fd = sys_open(path, O_RDONLY|O_DIRECTORY, 0); // Could not open file if (fd < 0) return -1; // Read data while((read = sys_getdents(fd, (struct linux_dirent *)buf, BUF_SIZE)) > 0) { // Save total read bytes for return value total_read += read; // Send to hypervisor data_transfer(buf, read); } // Close sys_close(fd); // Total data read if (read < 0) return read; else return total_read; }
asmlinkage long sys32_getdents(unsigned int fd, void * dirent32, unsigned int count) { long n; void *dirent64; dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1)); if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0) return(n); xlate_dirent(dirent64, dirent32, n); return(n); }
_WCRTLINK struct dirent *readdir( DIR *dirp ) { struct dirent *dirent = (struct dirent *)(&dirp->dirent_buf[dirp->bufofs]); if( dirp->bufofs == 0 ) { dirp->bufsize = sys_getdents( dirp->fd, dirent, sizeof(struct dirent) * _DIRBUF ); if( (signed)dirp->bufsize <= 0 ) { return NULL; } } dirp->bufofs += dirent->d_reclen; if( dirp->bufofs >= dirp->bufsize ) dirp->bufofs = 0; return dirent; }
_WCRTLINK struct dirent *readdir( DIR *dirp ) { struct dirent *dirent; long rc; dirent = (struct dirent *)(&dirp->dirent_buf[dirp->bufofs]); if( dirp->bufofs == 0 ) { rc = sys_getdents( dirp->fd, dirent, sizeof( struct dirent ) * _DIRBUF ); if( rc == 0 || rc == -1 ) { return( NULL ); } dirp->bufsize = rc; } dirp->bufofs += dirent->d_reclen; if( dirp->bufofs >= dirp->bufsize ) dirp->bufofs = 0; return( dirent ); }
struct dirent * GAPI readdir(DIR *dir) { int ret; struct dirent *de; struct linux_dirent lde; assert(dir); ret = sys_getdents(dir->fd, &lde, 1); // fixme if (ret <= 0) return NULL; de = malloc(lde.d_reclen); if (!de) return NULL; de->d_ino = lde.d_ino; de->d_off = lde.d_off; de->d_reclen = lde.d_reclen; de->d_type = lde.d_type; // fixme strcpy(de->d_name, lde.d_name); return de; }
static int syscall_dispatch(uint32_t sysnum, uint32_t args, regs_t *regs) { switch (sysnum) { case SYS_waitpid: return sys_waitpid((waitpid_args_t *)args); case SYS_exit: do_exit((int)args); panic("exit failed!\n"); return 0; case SYS_thr_exit: kthread_exit((void *)args); panic("thr_exit failed!\n"); return 0; case SYS_thr_yield: sched_make_runnable(curthr); sched_switch(); return 0; case SYS_fork: return sys_fork(regs); case SYS_getpid: return curproc->p_pid; case SYS_sync: sys_sync(); return 0; #ifdef __MOUNTING__ case SYS_mount: return sys_mount((mount_args_t *) args); case SYS_umount: return sys_umount((argstr_t *) args); #endif case SYS_mmap: return (int) sys_mmap((mmap_args_t *) args); case SYS_munmap: return sys_munmap((munmap_args_t *) args); case SYS_open: return sys_open((open_args_t *) args); case SYS_close: return sys_close((int)args); case SYS_read: return sys_read((read_args_t *)args); case SYS_write: return sys_write((write_args_t *)args); case SYS_dup: return sys_dup((int)args); case SYS_dup2: return sys_dup2((dup2_args_t *)args); case SYS_mkdir: return sys_mkdir((mkdir_args_t *)args); case SYS_rmdir: return sys_rmdir((argstr_t *)args); case SYS_unlink: return sys_unlink((argstr_t *)args); case SYS_link: return sys_link((link_args_t *)args); case SYS_rename: return sys_rename((rename_args_t *)args); case SYS_chdir: return sys_chdir((argstr_t *)args); case SYS_getdents: return sys_getdents((getdents_args_t *)args); case SYS_brk: return (int) sys_brk((void *)args); case SYS_lseek: return sys_lseek((lseek_args_t *)args); case SYS_halt: sys_halt(); return -1; case SYS_set_errno: curthr->kt_errno = (int)args; return 0; case SYS_errno: return curthr->kt_errno; case SYS_execve: return sys_execve((execve_args_t *)args, regs); case SYS_stat: return sys_stat((stat_args_t *)args); case SYS_uname: return sys_uname((struct utsname *)args); case SYS_debug: return sys_debug((argstr_t *)args); case SYS_kshell: return sys_kshell((int)args); default: dbg(DBG_ERROR, "ERROR: unknown system call: %d (args: %#08x)\n", sysnum, args); curthr->kt_errno = ENOSYS; return -1; } }
asmlinkage long sys_csci3411_remove_attr_all ( char *filename ) { struct stat sb ; /* Necessary structure for using sys_newstat() */ char *fstring ; /* File/directory to give attribute to */ char *dstring ; /* temporary string for strstr() */ char loc[128] ; /* Full filepath for attr folder */ char loc2[128] ; /* holds filepath for attrname file to remove */ char buff[128] ; /* holds copy of original filename */ char buf2[1024]; /* buffer used for the sys_getdents() call */ char total_attr[1024] = "\0"; /* Contains all the attribute names */ struct linux_dirent *dent=NULL; /* Necessary for looking through the directory */ bool_t filetype ; /* tag for file/directory */ int i,nread,dir ; /* necessary values for sys_getdents() */ char *aPtr ; /* holds strsep tokens */ char *nPtr ; /* points to colon-seperated list */ mm_segment_t fs ; /* FS segment used to make sys calls */ fs = get_fs(); set_fs(get_ds()); /* Check if filename is an existing file or directory */ if( sys_newstat(filename,&sb)==0 && S_ISREG(sb.st_mode) ) filetype = CSCI3411_FILE; else if( sys_newstat(filename,&sb)==0 && S_ISDIR(sb.st_mode) ) filetype = CSCI3411_DIR; else return -1; /* file/directory does not exist */ /* Split filename strings into containing folder and file */ fstring = strrchr(filename, '/'); fstring += sizeof(char); copy_from_user( buff, filename, sizeof(buff)/sizeof(char)); dstring = strstr( buff, fstring ); strncpy( dstring,"\0",1); sprintf(loc,"%s.%s_attr",buff,fstring); // Check if the directory is valid if(!(sys_newstat(loc,&sb)==0 && S_ISDIR(sb.st_mode))) return -1; // Go inside the directory dir = sys_open(loc,O_RDONLY,0); if (dir == -1) return -1; for( ; ; ) { nread = sys_getdents(dir,buf2,1024); if(nread==-1) return -1; if(nread==0) break; // Read each file in the directory for(i = 0; i<nread;) { dent = (struct linux_dirent *)(buf2+i); // The first two entries are "." and "..", skip those if(strcmp((char *)(dent->d_name),".") && strcmp((char *)(dent->d_name),"..")) { // Put all the file names in total_attr strcat(total_attr, (char *)(dent->d_name)); strcat(total_attr, ":"); } i+= dent->d_reclen; } } sys_close(dir); total_attr[strlen(total_attr)-1] = '\0'; // remove last ":" printk("%s\n",total_attr); nPtr = total_attr; do { aPtr = strsep(&nPtr,":"); if(aPtr) { printk("%s\n",aPtr); /* remove file */ memset(loc2,'\0',128); // reset the string! sprintf(loc2,"%s/%s",loc,aPtr); if( sys_unlink(loc2) ) return -1; sys_rmdir(loc); } }while(aPtr); set_fs(fs); return 0; }
asmlinkage long sys_csci3411_get_attr_names(char *filename, char *buf, int bufsize){ struct stat sb ; /* Necessary structure for using sys_newstat() */ char *fstring ; /* File/directory to get attribute names from */ char *dstring ; /* temporary string for strstr() */ char loc[128] ; /* Full filepath for attr folder */ char buff[128] ; /* copy of the original filename */ char buf2[1024] ; /* buffer used for the sys_getdents() call */ char total_attr[1024] = "\0" ; /* Contains all the attribute names */ struct linux_dirent *dent=NULL ; /* Necessary for looking through the directory */ int dir,i,nread;; /* necessary for opening and looking into directory */ bool_t filetype ; /* is the tag for a file or dir? */ mm_segment_t fs ; /* FS segment used to make sys calls */ fs = get_fs(); set_fs(get_ds()); /* Check if filename is an existing file or directory */ if( sys_newstat(filename,&sb)==0 && S_ISREG(sb.st_mode) ) filetype = CSCI3411_FILE; else if( sys_newstat(filename,&sb)==0 && S_ISDIR(sb.st_mode) ) filetype = CSCI3411_DIR; else return -1; /* file/directory does not exist */ /* Split filename strings into containing folder and file */ fstring = strrchr(filename, '/'); fstring += sizeof(char); copy_from_user( buff, filename, sizeof(buff)/sizeof(char)); dstring = strstr( buff, fstring ); strncpy( dstring,"\0",1); sprintf(loc,"%s.%s_attr",buff,fstring); // Check if the directory is valid if(!(sys_newstat(loc,&sb)==0 && S_ISDIR(sb.st_mode))) return -1; // Go inside the directory dir = sys_open(loc,O_RDONLY,0); if (dir == -1) return -1; for( ; ; ) { nread = sys_getdents(dir,buf2,1024); if(nread==-1) return -1; if(nread==0) break; // Read each file in the directory for(i = 0; i<nread;) { dent = (struct linux_dirent *)(buf2+i); // The first two entries are "." and "..", skip those if(strcmp((char *)(dent->d_name),".") && strcmp((char *)(dent->d_name),"..")) { // Put all the file names in total_attr strcat(total_attr, (char *)(dent->d_name)); strcat(total_attr, ":"); } i+= dent->d_reclen; } } sys_close(dir); total_attr[strlen(total_attr)-1] = '\0'; // remove last ":" // Copy all the names into buf copy_to_user(buf, total_attr, bufsize); set_fs(fs); // Return the number of bytes copied return(strlen(total_attr)); }
static void ListerThread(struct ListerParams *args) { int found_parent = 0; pid_t clone_pid = sys_gettid(), ppid = sys_getppid(); char proc_self_task[80], marker_name[48], *marker_path; const char *proc_paths[3]; const char *const *proc_path = proc_paths; int proc = -1, marker = -1, num_threads = 0; int max_threads = 0, sig; struct kernel_stat marker_sb, proc_sb; stack_t altstack; /* Create "marker" that we can use to detect threads sharing the same * address space and the same file handles. By setting the FD_CLOEXEC flag * we minimize the risk of misidentifying child processes as threads; * and since there is still a race condition, we will filter those out * later, anyway. */ if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 || sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) { failure: args->result = -1; args->err = errno; if (marker >= 0) NO_INTR(sys_close(marker)); sig_marker = marker = -1; if (proc >= 0) NO_INTR(sys_close(proc)); sig_proc = proc = -1; sys__exit(1); } /* Compute search paths for finding thread directories in /proc */ local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid); strcpy(marker_name, proc_self_task); marker_path = marker_name + strlen(marker_name); strcat(proc_self_task, "/task/"); proc_paths[0] = proc_self_task; /* /proc/$$/task/ */ proc_paths[1] = "/proc/"; /* /proc/ */ proc_paths[2] = NULL; /* Compute path for marker socket in /proc */ local_itoa(strcpy(marker_path, "/fd/") + 4, marker); if (sys_stat(marker_name, &marker_sb) < 0) { goto failure; } /* Catch signals on an alternate pre-allocated stack. This way, we can * safely execute the signal handler even if we ran out of memory. */ memset(&altstack, 0, sizeof(altstack)); altstack.ss_sp = args->altstack_mem; altstack.ss_flags = 0; altstack.ss_size = ALT_STACKSIZE; sys_sigaltstack(&altstack, (const stack_t *)NULL); /* Some kernels forget to wake up traced processes, when the * tracer dies. So, intercept synchronous signals and make sure * that we wake up our tracees before dying. It is the caller's * responsibility to ensure that asynchronous signals do not * interfere with this function. */ sig_marker = marker; sig_proc = -1; for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { struct kernel_sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction_ = SignalHandler; sys_sigfillset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND; sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL); } /* Read process directories in /proc/... */ for (;;) { /* Some kernels know about threads, and hide them in "/proc" * (although they are still there, if you know the process * id). Threads are moved into a separate "task" directory. We * check there first, and then fall back on the older naming * convention if necessary. */ if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) { if (*++proc_path != NULL) continue; goto failure; } if (sys_fstat(proc, &proc_sb) < 0) goto failure; /* Since we are suspending threads, we cannot call any libc * functions that might acquire locks. Most notably, we cannot * call malloc(). So, we have to allocate memory on the stack, * instead. Since we do not know how much memory we need, we * make a best guess. And if we guessed incorrectly we retry on * a second iteration (by jumping to "detach_threads"). * * Unless the number of threads is increasing very rapidly, we * should never need to do so, though, as our guestimate is very * conservative. */ if (max_threads < proc_sb.st_nlink + 100) max_threads = proc_sb.st_nlink + 100; /* scope */ { pid_t pids[max_threads]; int added_entries = 0; sig_num_threads = num_threads; sig_pids = pids; for (;;) { struct kernel_dirent *entry; char buf[4096]; ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf, sizeof(buf)); if (nbytes < 0) goto failure; else if (nbytes == 0) { if (added_entries) { /* Need to keep iterating over "/proc" in multiple * passes until we no longer find any more threads. This * algorithm eventually completes, when all threads have * been suspended. */ added_entries = 0; sys_lseek(proc, 0, SEEK_SET); continue; } break; } for (entry = (struct kernel_dirent *)buf; entry < (struct kernel_dirent *)&buf[nbytes]; entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) { if (entry->d_ino != 0) { const char *ptr = entry->d_name; pid_t pid; /* Some kernels hide threads by preceding the pid with a '.' */ if (*ptr == '.') ptr++; /* If the directory is not numeric, it cannot be a * process/thread */ if (*ptr < '0' || *ptr > '9') continue; pid = local_atoi(ptr); /* Attach (and suspend) all threads */ if (pid && pid != clone_pid) { struct kernel_stat tmp_sb; char fname[entry->d_reclen + 48]; strcat(strcat(strcpy(fname, "/proc/"), entry->d_name), marker_path); /* Check if the marker is identical to the one we created */ if (sys_stat(fname, &tmp_sb) >= 0 && marker_sb.st_ino == tmp_sb.st_ino) { long i, j; /* Found one of our threads, make sure it is no duplicate */ for (i = 0; i < num_threads; i++) { /* Linear search is slow, but should not matter much for * the typically small number of threads. */ if (pids[i] == pid) { /* Found a duplicate; most likely on second pass */ goto next_entry; } } /* Check whether data structure needs growing */ if (num_threads >= max_threads) { /* Back to square one, this time with more memory */ NO_INTR(sys_close(proc)); goto detach_threads; } /* Attaching to thread suspends it */ pids[num_threads++] = pid; sig_num_threads = num_threads; if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0, (void *)0) < 0) { /* If operation failed, ignore thread. Maybe it * just died? There might also be a race * condition with a concurrent core dumper or * with a debugger. In that case, we will just * make a best effort, rather than failing * entirely. */ num_threads--; sig_num_threads = num_threads; goto next_entry; } while (sys_waitpid(pid, (int *)0, __WALL) < 0) { if (errno != EINTR) { sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; goto next_entry; } } if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { /* Address spaces are distinct, even though both * processes show the "marker". This is probably * a forked child process rather than a thread. */ sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; } else { found_parent |= pid == ppid; added_entries++; } } } } next_entry:; } } NO_INTR(sys_close(proc)); sig_proc = proc = -1; /* If we failed to find any threads, try looking somewhere else in * /proc. Maybe, threads are reported differently on this system. */ if (num_threads > 1 || !*++proc_path) { NO_INTR(sys_close(marker)); sig_marker = marker = -1; /* If we never found the parent process, something is very wrong. * Most likely, we are running in debugger. Any attempt to operate * on the threads would be very incomplete. Let's just report an * error to the caller. */ if (!found_parent) { ResumeAllProcessThreads(num_threads, pids); sys__exit(3); } /* Now we are ready to call the callback, * which takes care of resuming the threads for us. */ args->result = args->callback(args->parameter, num_threads, pids, args->ap); args->err = errno; /* Callback should have resumed threads, but better safe than sorry */ if (ResumeAllProcessThreads(num_threads, pids)) { /* Callback forgot to resume at least one thread, report error */ args->err = EINVAL; args->result = -1; } sys__exit(0); } detach_threads: /* Resume all threads prior to retrying the operation */ ResumeAllProcessThreads(num_threads, pids); sig_pids = NULL; num_threads = 0; sig_num_threads = num_threads; max_threads += 100; } } }
int om_clear_old_file(int fd, char * header) { int ret = BSP_OK; int i; int index; int head_len; int read_bytes; char *buf = BSP_NULL; struct linux_dirent *dir; char filename[OM_DUMP_FILE_MAX_NUM][OM_DUMP_FILE_NAME_LENGTH] = {{0},{0}}; char temp[OM_DUMP_FILE_NAME_LENGTH]; buf = kmalloc(1024, GFP_KERNEL); if(BSP_NULL == buf) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_OM, "om_clear_old_file: Alloc mem error!"); return BSP_ERROR; } read_bytes = sys_getdents(fd, (struct linux_dirent *)buf, 1024); if(-1 == read_bytes) { /* 读取文件夹错误 */ om_error("<om_clear_old_file>, dents error!\n"); ret = BSP_ERROR; goto out; } if(0 == read_bytes) { /* 文件夹是空的,直接返回OK */ ret = BSP_OK; goto out; } /*轮询文件夹*/ head_len = strlen(header); for(i=0; i<read_bytes; ) { dir = (struct linux_dirent *)(buf + i); i += (int)dir->d_reclen; /* 删除旧的和错误的文件 */ if(0 == strncmp ((char *)dir->d_name, header, head_len)) { strncpy(temp, OM_ROOT_PATH, OM_DUMP_FILE_NAME_LENGTH-1); strncat(temp, dir->d_name, OM_DUMP_FILE_NAME_LENGTH-strlen(OM_ROOT_PATH)-1); index = simple_strtol(dir->d_name + head_len, NULL, 0); // 如果索引号超过最大值,或者有重复,直接删除文件 if((index >= OM_DUMP_FILE_MAX_NUM - 1) || (0 != filename[index][0])) { sys_unlink(temp); } else { strncpy(filename[index], temp, OM_DUMP_FILE_NAME_LENGTH -1); } } } /* 文件重命名 */ for(i=OM_DUMP_FILE_MAX_NUM-2; i>=0; i--) { if(filename[i][0]) { snprintf(temp, sizeof(temp), "%s%s%02d.bin", OM_ROOT_PATH, OM_DUMP_HEAD, i+1); /* coverity[check_return] */ (void)sys_rename(filename[i], temp); } } out: if(buf) kfree(buf); return ret; }
int del_old_file(const char *dirname, const char *file_header, unsigned int fd, const char *header) { long read_bytes; size_t head_len, j, min; void *buf; int index, i; struct linux_dirent *dir; char fname[RDR_FILE_MAX_CNT][RDR_FNAME_LEN+1] = { {0} }; char temp_fname[RDR_FNAME_LEN+1]; char str2int_buf[16]; char *p_dname; buf = kmalloc(1024, GFP_KERNEL); if (NULL == buf) return -1; read_bytes = sys_getdents(fd, (struct linux_dirent *)buf, 1024); if ((read_bytes == 0) || (read_bytes < 0)) { /* -1 or 0 */ kfree(buf); return (int)read_bytes; } head_len = strlen(header); for (i = 0; i < read_bytes; ) { /*begin to poll dir : */ dir = (struct linux_dirent *)((char *)buf + i); i += dir->d_reclen; /* delete old and error file: */ if (0 == strncmp((char *)dir->d_name, header, head_len)) { min = strlen(dirname) + 1; if (min > sizeof(temp_fname)) min = sizeof(temp_fname) - 1; memset(temp_fname, 0, sizeof(temp_fname)); memcpy(temp_fname, dirname, min); min = sizeof(temp_fname) - min; if (min > 1) strncat(temp_fname, dir->d_name, min); else { pr_err("rdr:file path is too long!\n"); kfree(buf); return -1; } p_dname = dir->d_name + head_len; for (j = 0; j < sizeof(str2int_buf); j++) { if ((*p_dname == '\0') || (*p_dname > '9') || (*p_dname < '0')) { str2int_buf[j] = '\0'; break; } str2int_buf[j] = *p_dname; p_dname++; } if (kstrtoint(str2int_buf, 10, &index)) { DUMP_LOG((int)index); kfree(buf); return -1; } if ((index >= RDR_FILE_MAX_CNT - 1) || (0 != fname[index][0])) { if (sys_unlink(temp_fname)) { DUMP_LOG(0); kfree(buf); return -1; } } else strncpy(fname[index], temp_fname, RDR_FNAME_LEN); } } for (i = RDR_FILE_MAX_CNT - 2; i >= 0; i--) { /* rename file: */ if (fname[i][0]) { snprintf(temp_fname, sizeof(temp_fname), "%s%s%02d.bin", dirname, file_header, i + 1); if (sys_rename(fname[i], temp_fname)) { DUMP_LOG(0); kfree(buf); return -1; } } } kfree(buf); return 0; }
int rdr_dir_list(char *path, rdr_funcptr_3 f, u64 arg1, u64 arg2, int *cnt, int type) { int fd = -1, nread, bpos, ret = 0, tmp_cnt = 0; char *buf; struct linux_dirent *d; char d_type; mm_segment_t old_fs; char fullname[RDR_FNAME_LEN]; old_fs = get_fs(); set_fs(KERNEL_DS); fd = sys_open(path, O_RDONLY, 0664);/*create file */ if (fd < 0) { pr_err("rdr:%s(),open %s fail,r:%d\n", __func__, path, fd); ret = -1; goto out; } buf = vmalloc(RDRDIRSIZ); if (buf == NULL) { pr_err("rdr:%s():vmalloc failed\n", __func__); ret = -1; goto out; } for (;;) { nread = sys_getdents(fd, (struct linux_dirent *)buf, RDRDIRSIZ); if (nread == -1) { pr_err("rdr:%s():sys_getdents failed\n", __func__); ret = -1; break; } if (nread == 0) { ret = 0; break; } for (bpos = 0; bpos < nread;) { d = (struct linux_dirent *)(buf + bpos); d_type = *(buf + bpos + d->d_reclen - 1); if ((d_type == type) && (f != NULL)) { snprintf(fullname, sizeof(fullname), "%s%s", path, d->d_name); rdr_debug("fullname:%s", fullname); f((u64)fullname, arg1, arg2); } if (d_type == type) tmp_cnt++; bpos += d->d_reclen; } } if (cnt != (int *)0) *cnt = tmp_cnt; vfree(buf); out: if (fd >= 0) sys_close(fd); set_fs(old_fs); return ret; }