/*-
* Copyright (C), 1988-2014, mymtom
*
* vi:set ts=4 sw=4:
*/
#ifndef lint
static const char rcsid[] = "$Id$"
#endif /* not lint */
/**
* @filelast20.c
* @brief
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
char *memchrr(const void *v1, const char *v2, int c)
{
char *s1, *s2
char *p
s1 = (char *)v1
s2 = (char *)v2
for (p = s2p >= s1--p) {
if (*p == c)
return p
}
return NULL
}
#define READSIZE1024
int main(int argc, char *argv[])
{
int ret
FILE *fp
char *addr
size_t len
int prot
int flags
int fd
off_t off
off_t rem
long pagesize
struct stat buf
pagesize = sysconf(_SC_PAGESIZE)
fp = fopen("last20.c", "rb")
fd = fileno(fp)
ret = fstat(fd, &buf)
if (buf.st_size <= READSIZE || buf.st_size <= pagesize) {
off = 0
len = buf.st_size
} else {
off = buf.st_size - READSIZE
rem = off % pagesize
off = off - rem
len = READSIZE + rem
}
/*
printf("size=%d READSIZE=%d off=%d len=%d\n",
(int)buf.st_size, (int)READSIZE, (int)off, (int)len)
*/
prot = PROT_READ
flags = MAP_PRIVATE
addr = mmap(NULL, len, prot, flags, fd, off)
fclose(fp)
{
int i, n
char *head, *tail
size_t size
char line[1024]
tail = addr + len - 1
n = 20
for (i = 0i <n++i) {
head = memchrr(addr, tail - 1, '\n')
if (head == NULL) {
size = tail - addr
memcpy(line, addr, size)
line[size] = '\0'
} else {
size = tail - head - 1
memcpy(line, head + 1, size)
line[size] = '\0'
tail = head
}
printf("%s\n", line)
if (head == NULL) {
break
}
}
}
munmap(addr, len)
return 0
}
运行结果为:
./last20 | tac | cat -n
line[size] = '\0'
} else {
size = tail - head - 1
memcpy(line, head + 1, size)
line[size] = '\0'
tail = head
}
printf("%s\n", line)
if (head == NULL) {
break
}
}
}
munmap(addr, len)
return 0
}
1,首先需要了解cp的原理。
2,可以参考cp的源码去了解其原理
3,cp命令的源码可以在linux内核中找到。
4,或者下载busybox其中也会有cp的源码
只有了解其原理之后才能谈如何实现。参考代码如下:
#include <stdio.h>#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#define BUF_SIZE 1024
#define PATH_LEN 128
void my_err(char *err_string, int line )
{
fprintf(stderr,"line:%d ",line)
perror(err_string)
exit(1)
}
void copy_data(const int frd,const int fwd)
{
int read_len = 0, write_len = 0
unsigned char buf[BUF_SIZE], *p_buf
while ( (read_len = read(frd,buf,BUF_SIZE)) ) {
if (-1 == read_len) {
my_err("Read error", __LINE__)
}
else if (read_len > 0) { //把读取部分写入目标文件
p_buf = buf
while ( (write_len = write(fwd,p_buf,read_len)) ) {
if(write_len == read_len) {
break
}
else if (write_len > 0) { //只写入部分
p_buf += write_len
read_len -= write_len
}
else if(-1 == write_len) {
my_err("Write error", __LINE__)
}
}
if (-1 == write_len) break
}
}
}
int main(int argc, char **argv)
{
int frd, fwd //读写文件描述符
int len = 0
char *pSrc, *pDes //分别指向源文件路径和目标文件路径
struct stat src_st,des_st
if (argc < 3) {
printf("用法 ./MyCp <源文件路径> <目标文件路径>\n")
my_err("arguments error ", __LINE__)
}
frd = open(argv[1],O_RDONLY)
if (frd == -1) {
my_err("Can not opne file", __LINE__)
}
if (fstat(frd,&src_st) == -1) {
my_err("stat error",__LINE__)
}
/*检查源文件路径是否是目录*/
if (S_ISDIR(src_st.st_mode)) {
my_err("略过目录",__LINE__)
}
pDes = argv[2]
stat(argv[2],&des_st)
if (S_ISDIR(des_st.st_mode)) { //目标路径是目录,则使用源文件的文件名
len = strlen(argv[1])
pSrc = argv[1] + (len-1) //指向最后一个字符
/*先找出源文件的文件名*/
while (pSrc >= argv[1] && *pSrc != '/') {
pSrc--
}
pSrc++//指向源文件名
len = strlen(argv[2])
// . 表示复制到当前工作目录
if (1 == len && '.' == *(argv[2])) {
len = 0 //没有申请空间,后面就不用释放
pDes = pSrc
}
else { //复制到某目录下,使用源文件名
pDes = (char *)malloc(sizeof(char)*PATH_LEN)
if (NULL == pDes) {
my_err("malloc error ", __LINE__)
}
strcpy(pDes,argv[2])
if ( *(pDes+(len-1)) != '/' ) { //目录缺少最后的'/',则补上’/‘
strcat(pDes,"/")
}
strcat(pDes+len,pSrc)
}
}
/* 打开目标文件, 使权限与源文件相同*/
fwd = open(pDes,O_WRONLY | O_CREAT | O_TRUNC,src_st.st_mode)
if (fwd == -1) {
my_err("Can not creat file", __LINE__)
}
copy_data(frd,fwd)
//puts("end of copy")
if (len > 0 && pDes != NULL)
free(pDes)
close(frd)
close(fwd)
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)