嵌入式学习笔记-文件IO、标准IO、目录IO

文件IO

1. 文件概述

  文件IO是从用户空间角度考虑的输入与输出,从内核读取数据或从文件中读取数据,写数据到内核或写数据到文件中。
  内核中有很多文件,应该写到哪一个文件中呢,或从哪一个文件中读呢?(内核应该负责管理这些文件-文件管理)
  因此在写入或读出之前用户应该指定某个文件,即要创建或打开某个文件

  即:read ,write 这二个函数应该有一个参数是指定某个文件
  read或write 函数之前有一个函数: open
  操作之后,还要关闭这些文件    close

2. 相关函数

open
read
write
close

  1. open – 打开或创建一个文件

open(char *, flag, mode)在fcntl.h文件中声明。函数的作用:创建或打开某个文件,参数:最多有三个参数;
第一个参数,char * 包含有文件名和路径
第二个参数:flag 打开文件的方式
第三个参数:mode 创建文件的权限。(如果是打开文件不需要这个参数,如果创建一个文件需要这个参数)

flag内容如下:

flag功能
O_RDONLY只读
O_WRONLY只写
O_RDWR读写
O_CREAT创建一个文件
O_EXCL如果使用O_CREAT时文件存在,则可返回错误消息。这一 参数可测试文件是否存在。
O_TRUNC打开文件(会把已经存在的内容给删除)。
O_APPEND追加方式打开文件(不会把已经存在的内容给删除)。

返回值:
  成功:文件描述符,它是一个非负的正整数,即文件的ID号,相当于人的身份证号;
  出错:-1。

open 函数创建文件时的权限是:
  == mode & (~umask)

B111 111 111 & ~(B 000 010 010) = B 111 101 101
也可以直接umask xxx,更改umask.

什么是文件描述符?
  内核的一个重要功能是文件管理,系统有非常多的文件,内核怎样认识每一个文件呢?内核采用ID号的方式标识这些文件,inode 号,inode号表示不同的文件,比如ls –lai,只要文件不一样,inode号就不一样。

那么这些内核的文件的ID号,在每个用户的程序中怎样映射的呢?即是文件描述符。

open函数的返回值就是这个ID号

ID号有什么规律呢?
从0开始累加,
程序进行时(进程),内核会自动打开3个文件描述符 0,1,2,分别对应,标准输入、输出和出错,这样在程序中,每打开一个文件,文件描述符值从3开始累加。

  1. write(int fd, void *buf, size_t count )

第一个参数:文件描述符,向哪一个文件中去写;
第二个参数:向这个文件中写什么内容;
第三个参数:向这个文件中写多少个。
函数的返回值:是实际写的字节数。

返回值:是实际写的字节数

  1. read(int fd, void *buf, size_t count)

第一个参数:文件描述符,从哪一个文件中去读;
第二个参数:读到什么地方去;
第三个参数:读多少个。
函数的返回值:是实际读的字节数。

返回值:是实际读的字节数

  1. lseek(int fd, off_t offset, int whence),该函数的头文件:sys/types.h unistd.

功能:调整读写的位置指针;

第一个参数:要调整的文件的文件描述符;

第二个参数:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移);

第三个参数:当前位置的基点,有三个标志,
SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小;
SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量。
SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小。函
数的

返回值:成功:文件当前的位置,出错:-1。

  1. close(fd)

调用close()函数可以关闭一个打开的文件。
调用成功返回0,出错返回-1,并设置errno;
注:当一个进程终止时,该进程打开的所有文件都由内核自动关闭;

例子:拷贝文件==》cp命令的实现
创建两个文件一个a.c一个b.c。
a. c有内容,b.c是空文件。

#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"

int main(int argc,char *argv[])
{
	int rd_fd,wr_fd;
	char read_buf[128]={0};
	int rd_ret=0;

	if(argc<3)
	{
		printf("please input src file and des file\n");
		return -1;
	}

	rd_fd=open(argv[1],O_RDONLY);
	if(rd_fd<0)
	{
		printf("open src file %s failure\n",argv[1]);
		return -2;
	}
	printf("open src file %s success,rd_fd=%d\n",argv[1],rd_fd);

	wr_fd=open(argv[2],O_WRONLY);
	if(wr_fd<0)
	{
		printf("open src file %s failure\n",argv[2]);
		return -3;
	}
	printf("open des file %s success,wd_fd=%d\n",argv[2],wr_fd);
	
	while(1)
	{
		rd_ret=read(rd_fd,read_buf,128);
		if(rd_ret<128)
			break;
		write(wr_fd,read_buf,rd_ret);
		memset(read_buf,0,128);   // clean cache
	}
	write(wr_fd,read_buf,rd_ret);
	
	close(rd_fd);
	
	return 0;
}

a.c内容如下:
在这里插入图片描述
操作过程:
在这里插入图片描述

标准IO

1 简介

与文件IO的区别?
  文件IO:是直接调用内核提供的系统调用函数, 头文件是unistd.h
  标准IO:是间接调用系统调用函数,头文件是: stdio.h
之前学过:输入输入相关的函数,都是和标准的输入(键盘),标准的输出(显示器)

标准IO中的相关函数,不仅可以读写普通文件,也可以向标准的输入或标准的输出中读或写。

2 测试验证库缓存的存在

三个缓存的概念(数组):

  1. 我们的程序中的缓存,就是你想从内核读写的缓存(数组)----用户空间的缓存
  2. 每打开一个文件,内核在内核空间中也会开辟一块缓存,这个叫内核空间的缓存
    文件IO中的写即是将用户空间中的缓存写到内核空间的缓存中。
    文件IO中的读即是将内核空间的缓存写到用户空间中的缓存中。
  3. 标准IO的库函数中也有一个缓存,这个缓存称为----库缓存

标准IO库函数在什么时候会调用系统调用函数?
标准IO库缓存写满或满足一定条件时,会调用系统调用函数。

int main()
{
  char buf[]="hello linux";
  printf("%s",buf);
  while(1);
  return 0;
}

这些都可以通过编译调试,看看是否有输出“hello linux”,观察现象。下面的都是类似。

printf满足一定条件 : 遇到\n 时,即会将库缓存的内容写到内核中,即调用了系统调用函数。

#include "stdio.h"
int main()
{
  char buf[]="hello linux\n";
  printf("%s",buf);
  while(1);
  return 0;
}

库缓存写满时,会调用系统调用函数,将lib_buffer 内容写到kernel_buffer中去

#include "stdio.h"
int main()
{
  char buf[]="hello linux";
  int i=0;
  while(i< 93)
  {
    printf("%s",buf);
	i++;
  }
  printf("h");
  while(1);
  return 0;
}

3 相关函数

文件IO标准IO
openfopen
closefclose
lseekfseek, rewind
read读函数比较多(分三类,全缓存、行缓存和无缓存)
write读函数比较多(分三类,全缓存、行缓存和无缓存)
  1. FILE *fopen (const char *path, const char *mode)

返回值:FILE * 文件流指针 类似于文件IO 中的文件描述符

FILE 定义:struct _IO_FILE,在/usr/include/libio.h

包含读写缓存的首地址、大小、位置指针等。

标准的输入流:stdin 0
标准的输出流:stdout 1
标准的出错流:stderr 2

Mode 类似于文件IO中的 flag

b二进制文件
r只读方式打开文件,文件必须存在;
w或a只写方式打开文件,文件不存在则创建;区别:w等价O_TRUNC,a等价O_APPEND;
+读写方式打开文件,文件必须存在;

例:以读写方式打开一个文件,该文件必须存在: r+
以追加方式打开一个文件,若文件不存在,则创建: a或a+

  1. int fclose(FILE *stream)
    fclose()调用成功返回0,失败返回EOF,并设置errno

在该文件被关闭之前,刷新缓存中的数据。如果标准 I/O 库已经为该流自动分配了一个缓存,则释放此缓存。
下面看一个例子:
打开一个文件,如果没有就创建一个。

#include "stdio.h"
int main(int argc, char *argv[])
{
	FILE *fp;
	fp=fopen(argv[1],"a+");
	if(fp=NULL)
	{
		printf("creat file %s failure\n",argv[1]);
		return -1;
	}
	printf("creat file %s success\n",argv[1]);
	fclose(fp);
	 
	return 0;
}
  1. 读写函数:

三类读写函数:

一类:行缓存 遇到新行符(\n) 或写满缓存时,即调用系统调用函数
读:fgets, gets, printf, fprintf,sprintf
写:fputs, puts,scanf

一个字符的读写,是否是行缓存?
读:fgetc, getc, getchar
写:fputc, putc,putchar

二类:无缓存 只要用户调这个函数,就会将其内容写到内核中

三类:全缓存 只有写满缓存再调用系统调用函数
读:fread
写:fwrite

3.1 行缓存的读写函数fgetsfputs

char *fgets (char *s, int size, FILE *stream)

第一个参数:缓存,即读到哪里去
第二个参数:读多少个字节
第三个参数:从什么地方读
返回值若成功则为s(缓存的地址),若已处文件尾端或出错则为null

int fputs(const char *s,FILE *stream);

第一个参数:缓存,即写什么内容
第二个参数:写到哪里去
若成功则为非负值,若出错则为EOF -1

3.2 刷新缓存函数:fflush(FILE *fp)
把库函数中的缓存的内容强制写到内核中。

3.3 无缓存:stderr
stdout 行缓存

3.4 调整读写位置指针函数:

fseek() 参数与lseek是一样的但是返回值不一样

lseek的返回值是:当前文件的位置指针值;

fseek()的返回值是:成功返回0,失败返回-11;

rewind(FILE *fp) 用于设定流的文件位置指示为文件开始,该函数调用成功无返回值。

rewind()等价于(void)fseek(fp 0, SEEK_SET)

ftell(FILE *fp)用于取得当前的文件位置,调用成功则为当前文件位置指示,若出错则为-1L;

3.5 行缓存的读写函数getsputs

char *gets(char *s); 

int puts(const char *s);

getsfgets的区别:

gets()时不能指定缓存的长度,这样就可能造成缓存越界(如若该行长于缓存长度),写到缓存之后的存储空间中,从而产生不可预料的后果;

gets()只能从标准输入中读;

gets()fgets()的另一个区别是: gets()并不将新行符存入缓存中, fgets 将新行符存入缓存中;

putsfputs的区别:

puts()只能向标准输出中写;

puts()fputs()的另一个区别是: puts 输出时会添加一个新行符, fputs不会添加;

例如下面这个例子:

#include "stdio.h"
#include "string.h"

int main()
{
	char buf[128] = {0};
	int len;

	puts("gets()输入:");
	gets(buf);
	len=strlen(buf);
	printf("len=%d\n",len);

	fputs("fgets()输入:",stdin);
	fgets(buf,128,stdin);
	len=strlen(buf);
	printf("len=%d\n",len);
	puts(buf);

	return 0;
}

输出结果显示:

在这里插入图片描述

3.6 fprintf、printf、sprintf 行缓存的函数

int fprintf(FILE *stream,”字符串格式”)   

fprintf可以输出到文件中,也可输出到显示器,
printf 只能输出到显示器中。

int sprintf(str *, “字符串格式”)

输出内容到一个字符串中

3.7 一个字符读写函数fgetcfputc

int fgetc(FILE *fp)

功能:从文件中读取一个字符;
参数:文件流
返回值:正确为读取的字符,到文件结尾或出错时返回EOF。

int fputc(int c, FILE *fp)

功能:写一个字符到文件中
参数:第一个参数为要写的字符,第二个参数为文件流
返回值:成功则返回输入的字符,出错返回EOF。

fputc有缓存,但不是行缓存函数
证明:

#include "stdio.h"

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

	fp=fopen("./a.c","w+");
	if(fp==NULL)
	{
		printf("open file a.c failure\n");
		return -1;
	}
	printf("open file a.c success\n");

	// fputc('a',fp);
	// fputc('\n',fp);
	// fflush(fp);

	while(1);
	fclose(fp);
	return 0;
}

将注释的先后打开,观察现象。

char *fgets (char *s, int size, FILE *stream)

返回值若成功则为s(缓存的地址),若已处文件结尾或读错则为null

int fgetc(FILE *fp)

返回值:正确为读取的字符,到文件结尾或读错时返回EOF。

3.8 int feof(FILE *stream)
功能:判断是否已经到文件结束
参数:文件流
返回值:到文件结束,返回为非0,没有则返回0

3.9 int ferror(FILE *stream);
功能:判断是否读写错误
参数:文件流
返回值:是读写错误,返回为非0,不是则返回0

3.10 void clearerr(FILE *stream);
功能:清除流错误
参数:文件流

例子:

#include "stdio.h"
#include "string.h"

int main(int argc,char *argv[])
{
	FILE *fp;
	char *ret;
	char buf[]="hello linux\n";
	char readbuf[128]={0};
	fp=fopen("./a.c","w+");
	if(fp==NULL)
	{
		printf("open file a.c failure\n");
		return -1;
	}
	printf("open file a.c success\n");

	fputs(buf,fp);
	rewind(fp);
	fgets(readbuf,128,fp);
	printf("readbuf:%s",readbuf);

	memset(readbuf,0,128); //clear memory
	ret=fgets(readbuf,128,fp);
	printf("seconf readbuf=%s,ret=%p\n",readbuf,ret);
	printf("feof=%d,ferror=%d\n",feof(fp),ferror(fp));
	clearerr(fp); // clear error
	printf("clear error after:feof=%d,ferror=%d\n",feof(fp),ferror(fp));
	fclose(fp);

	return 0;
}

输出结果:
在这里插入图片描述
实验:cat命令的实现
linux内核实现cat命令的架构:
在这里插入图片描述
下面通过fputc/fgetc来实现:

#include "stdio.h"

int main(int argc,char *argv[])
{
	FILE *src_fp;
	int read_ret;
	if(argc < 2)
	{
		printf("please input src file\n");
		return -1;
	}

	src_fp=fopen(argv[1],"r");
	if(src_fp == NULL)
	{
		printf("open file file %s failure\n",argv[1]);
		return-2;
	}
	printf("open src file %s success\n",argv[1]);
	// start read write
	while(1)
	{
		read_ret=fgetc(src_fp);
		if(feof(src_fp))
		{
			printf("read file %s end\n",argv[1]);
			break;
		}
		fputc(read_ret,stdout); // 当一个进程打开时,内核自动打开三个文件(输入,输出,错误)	
	}
	
	fclose(src_fp);
	return 0;
}

在这里插入图片描述
通过fputs/fgets来实现:

#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
#include "string.h"

int main(int argc,char *argv[])
{
	FILE *src_fp;
	int read_ret;
	char read_buf[128];
	char *buf;
	int i=0;
	if(argc < 2)
	{
		printf("please input src file\n");
		return -1;
	}

	src_fp=fopen(argv[1],"r");
	if(src_fp == NULL)
	{
		printf("open file file %s failure\n",argv[1]);
		return -2;
	}
	printf("open src file %s success\n",argv[1]);
	// start read write
	while(1)
	{
		buf=fgets(read_buf,128,src_fp);
		i=i+1;
		printf("i=%d\n",i);
		
		if(feof(src_fp))
		{
			printf("read file %s end\n",argv[1]);
			break;
		}
		fputs(read_buf,stdout);
	}
	
	fclose(src_fp);
	return 0;
}

在这里插入图片描述

3.11 全缓存的二个函数:

  1. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

  2. size_t fwrite(const void *ptr, size_t size, size_t nmemb,
    FILE *stream);

第一个参数 buf:写的内容
第四个参数 fp:写到哪里去
第二个参数 size:写的内容中,每一个单元所占的字节数
第三个参数 nmemb:写的内容中,有多少个单元数
总共写多少个字节,size*nmemb
比如定义了一个char buf[128],那么这里就是size就是1(char占一个字节),nmemb就是128。
返回值:实际写的单元数。

实验:

#include "stdio.h"

int main(int argc,char *argv[])
{
	FILE *fp;
	char buf[]="hello linux";
	char readbuf[128]={0};
	fp=fopen(argv[1],"w+");
	if(fp==NULL)
	{
		printf("open file a.c failure\n");
		return -1;
	}

	printf("open file a.c success\n");
	fwrite(buf,sizeof(char),sizeof(buf),fp);
	rewind(fp); //fseek(fp,0,SEEK_SET);
	fread(readbuf,sizeof(char),sizeof(readbuf),fp);
	printf("readbuf:%s\n",readbuf);
	fclose(fp);
	return 0;
}

在这里插入图片描述

3.12
(1) fseek() 参数与lseek是一样的
但是返回值不一样
Lseek的返回值是:当前文件的位置指针值
fseek()的返回值是:成功返回0,失败返回-1,并设置errno

(2)ftell(FILE *fp)
用于取得当前的文件位置,调用成功则为当前文件位置指示,若出错则为-1L

(3) rewind(FILE *fp) 用于设定流的文件位置指示为文件开始,该函数调用成功无返回值。
rewind()等价于(void)fseek(fp 0, SEEK_SET)

(4) fflush(FILE *fp)
把库函数中的缓存的内核强制写到内核中。

Linux下静态库和动态库(共享库)的制作与使用

Linux操作系统支持的函数库分为:

静态库,libxxx.a,在编译时就将库编译进可执行程序中。
优点:程序的运行环境中不需要外部的函数库。
缺点:可执行程序大

动态库,又称共享库,libxxx.so在运行时将库加载到可执行程序中。
优点:可执行程序小。
缺点:程序的运行环境中必须提供相应的库。

静态库的制作:

  1. 生成目标文件: gcc -c -o xxx.o xxx.c
  2. 将目标文件生成静态函数库,创建命令ar
    ar  -cr  -o xxx.a  xxx.o

-c: create的意思
-r: replace的意思,表示当插入的模块file.o已经存在libfile.a中,则覆盖。反之ar显示一个错误消息。

操作静态库的几个实例:
情况1: 如果从别处得到一个静态库libunknown.a,想知道其中包含哪些模块。
命令:ar -t libunknown.a

静态库的编译:gcc  -o  main  main.c  -L.  -lfile编译main.c就会把静态函数库整合进main。

其中:
-L指定静态函数库的位置供查找,注意L后面还有’.’,表示静态函数库在本目录下查找。
-l则指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略。

 删除libaddsub.a后main依然可以运行,因为静态库的内容已经整合进去了。

实验:
查看两个文件内容:
在这里插入图片描述
生成静态库:


动态函数库的制作:

  1. 生成目标文件:gcc -c -o xxx.o xxx.c

  2. gcc -shared -fpic -o libxxx.so xxx.o
    -fpic:产生位置无关代码。
    -shared:生成共享库。

用上述命令生成libaddsub.so 动态函数库。

gcc -o main  main.c  -L.  -lxxx

此时还不能立即./main,因为在动态函数库使用时,会查找/usr/lib/lib目录下的动态函数库,而此时我们生成的库不在里边。

第一种方法:
libaddsub.so放到/usr/lib/lib中去。

第二种方法,假设libxxx.so/home/llc/test/day2/2 环境变量方法

 export LD_LIBRARY_PATH=/home/llc/test/day2/2

第三种方法:
/etc/ld.so.conf文件里加入我们生成的库的目录,然后ldconfig /etc/ld.so.conf运行刚才修改的shell脚本(在root权限下运行)。

目录IO

相关函数

目录I/O与文件I/O函数的比较

目录I/O文件I/O
opendir只能打开目录
mkdir 创建目录open
readdir 读目录read
rewinddir 调整位置指针rewind
telldirftell
seekdirfseek
closedir:关闭目录close
  1. opendir
DIR *opendir(const char *pathname) 

参数:打开的目录以及路径
返回值:成功返回目录流指针,出错返回NULL。

int mkdir(const char  * path,  mode_t  mode) 

path为欲创建的目录文件路径,
mode为该目录的访问权限
返回值:若目录创建成功,则返回0;否则返回-1
生成的目录权限仍和umask有关系。

  1. readdir
struct dirent *readdir(DIR *dr)

参数:目录流指针
返回值:成功则为struct dirent指针,若在目录尾或出错则返回NULL。
struct dirent定义在头文件dirent.h中。
此结构至少包含下列两个成员:

 struct dirent
 {
    ino_t d_ino;      // inode 号
    char d_name[NAME_MAX+1]; //文件名
 } 
  1. rewinddir:重置读取目录流的位置为开头
void rewinddir(DIR *dr)

参数:目录流指针

long telldir(DIR *dirp) 

参数:目录流指针
返回值:目录流当前位置

void seekdir(DIR *dirp , long loc) 

类似于文件定位函数fseek(),在目录流上设置下一个readdir()操作的位置。
参数:目录流指针和偏移量

  1. closedir
    int close(DIR *dr)

参数:目录流指针
返回值:成功返回 0,出错返回- 1。

实验:
打开一个目录,并且将该目录下的子文件和子目录都读出来。
注意:目录下的子文件和子目录存放方式以链表的形式存放,每读取完一个链表,指针指向下一个链表,直到读取完成。用到的函数不知道怎么用,可以直接输入man xxx,查询帮组。

#include "stdio.h"
#include "sys/types.h"
#include "dirent.h"

int main(int argc,char *argv[])
{
	int ret;
	DIR *dp;
	struct dirent *dir;
	if(argc<2)
	{
		printf("please input open directory name\n");
		return -1;
	}

	dp=opendir(argv[1]);
	if(dp == NULL)
	{
		printf("open mydir failure\n");
		return -2;
	}
	printf("open mydir success\n");
	while(1)
	{
		dir=readdir(dp);
		if(dir != NULL)
		{
			printf("inode=%ld,name=%s\n",dir->d_ino,dir->d_name);
		}
		else
			break;
	}
	closedir(dp);
	 
	return 0;
}

综合实例:单机模式下的文件上传送和下载

(1) 输入服务器的地址: 路径和目录名
(2) 列出服务器中有哪些文件: opendir readdir
(3) 输入从服务器下载的文件名 或 上传文件到服务器的文件名
(4) 文件下载 或 文件上传送
文件IO: open read write close
标准IO fopen fputs fgets fputc fgetc fread fwrite fclose

第一实验:下载文件

#include "stdio.h"
#include "sys/types.h"
#include "dirent.h"
#include "string.h"
#include "unistd.h"
#include "fcntl.h"

int main()
{
        DIR *dp;
        int src_fd,des_fd;
        int fd,ret;
        struct dirent *dir;
        char server[128]={0};
        char file[128]={0};
        char buf[128]={0};
start:
        printf("please input server PATH and Directory name\n");
        scanf("%s",server);
        //list server files
        dp=opendir(server);
        if(dp==NULL)
        {
                printf("open server:%s faliure\n",server);
                goto start;
        }
        printf("open server:%s success\n",server);
        // show table
        while(1)
        {
                dir=readdir(dp);
                if(dir==NULL)
                        break;
                else
                {
                        printf("inode=%ld\t file_name=%s\n",dir->d_ino,dir->d_name);
                }
        }
        printf("\n Please input download file\n");
        scanf("%s",file);
        //open server file
        src_fd=open(strcat(strcat(server,"/"),file),O_RDONLY);
        if(src_fd<0)
        {
                printf("open download file%s failure\n",file);
                return -1;
        }
        printf("open download file%s success\n",file);
        des_fd=open(file,O_CREAT|O_WRONLY,0777);
        if(des_fd<0)
        {
                printf("creat file %s failure\n",file);
                return -2;
        }
        printf("creat file %s success\n",file);
        //content is written to the file
        while(1)
        {
                ret=read(src_fd,buf,128);
                write(des_fd,buf,ret);
                if(ret<128)
                        break;
        }
        close(src_fd);
        close(des_fd);
        closedir(dp);

        return 0;
}

在这里插入图片描述
第一实验:上传文件

#include "stdio.h"
#include "sys/types.h"
#include "dirent.h"
#include "string.h"
#include "unistd.h"
#include "fcntl.h"

int main()
{
        DIR *dp;
        int src_fd,des_fd;
        int fd,ret;
        struct dirent *dir;
        char client[128]={0};
        char file[128]={0};
        char buf[128]={0};
start:
        printf("please input client PATH and Directory name\n");
        scanf("%s",client);
        //list server files
        dp=opendir(client);
        if(dp==NULL)
        {
                printf("open client erver:%s faliure\n",client);
                goto start;
        }
        printf("open client:%s success\n",client);

        while(1)
        {
                dir=readdir(dp);
                if(dir==NULL)
                        break;
                else
                {
                        printf("inode=%ld\t file_name=%s\n",dir->d_ino,dir->d_name);
                }
        }
        printf("\n Please input upload file\n");
        scanf("%s",file);
        // open src file, only read
        src_fd=open(strcat(strcat(client,"/"),file),O_RDONLY);

        printf("please input des:\n");
        // input absolute path,read and write way
        scanf("%s",file);
        des_fd=open(file,O_CREAT|O_WRONLY,0644);
        if(des_fd<0)
        {
                printf("open client des file %s failure\n",file);
                return -1;
        }
        printf("open client file success\n");

        while(1)
        {
                ret=read(src_fd,buf,128);
                write(des_fd,buf,ret);
                if(ret<128) //return less 128 exit loop
                        break;
        }
        close(src_fd);
        close(des_fd);
        closedir(dp);

        return 0;
}

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值