lstat(传入路径参数,&一种struct)返回0或1

本文详细解读了apue04.pdf中关于文件类型判断的代码实现,包括符号链接和套接字的特殊判断逻辑,通过使用lstat函数配合宏定义来识别不同类型的文件和目录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

apue 04.pdf

S _ I S L N K ( )
S _ I S S O C K ( )
符号连接( P O S I X . 1 或 S V R 4无此类型) 套接字( P O S I X . 1 或 S V R 4无此类型)
为了跨平台,代码写成#ifdef这种
#include "apue.h"

int
main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr;

for (i = 1; i < argc; i++) {
printf("%s: ", argv[i]);
if (lstat(argv[i], &buf) < 0) {
err_ret("lstat error");
continue;
}
if (S_ISREG(buf.st_mode))
ptr = "regular";
else if (S_ISDIR(buf.st_mode))
ptr = "directory";
else if (S_ISCHR(buf.st_mode))
ptr = "character special";
else if (S_ISBLK(buf.st_mode))
ptr = "block special";
else if (S_ISFIFO(buf.st_mode))
ptr = "fifo";
#ifdef S_ISLNK
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
#endif
#ifdef S_ISSOCK
else if (S_ISSOCK(buf.st_mode))
ptr = "socket";
#endif
else
ptr = "** unknown mode **";
printf("%s\n", ptr);
}
exit(0);
}

这样定义的
#define S_ISDIR (mode) (((mode) & S_IFMT) == S_IFDIR)
帮我阅读httpd代码 void accept_request(void *arg) { //pthread_create传过来的参数(void *)(intptr_t)client_sock int client = (intptr_t)arg; char buf[1024]; /*size_t是标准C库中定义的,应为unsigned int,在64位系统中为 long unsigned int。数据类型&quot;socklen_t&quot;和int应该具有相同的长度, 否则就会破坏 BSD套接字层的填充。*/ size_t numchars; char method[255]; char url[255]; char path[512]; size_t i, j; /*在使用这个结构体和方法时,需要引入:&lt;sys/types.h&gt;、&lt;sys/stat.h&gt; struct stat这个结构体是用来描述一个linux系统文件系统中的文件属性 的结构。有两种方法获得一个文件的属性 第一种是通过路径有两个函数可以得到 int stat(const char *path, struct stat *struct_stat); int lstat(const char *path,struct stat *struct_stat); 两个函数的第一个参数都是文件的路径,第二个参数struct stat的指针。 返回值为0,表示成功执行。执行失败是,error被自动设置对应值。 这两个方法区别在于stat没有处理字符链接(软链接)的能力, 如果一个文件是符号链接,stat会直接返回它所指向的文件的属性; 而lstat返回的就是这个符号链接的内容。 (符号连接就是软连接,软链接的内容就是一个字符串。这个字符串就是它所链接的文件的绝对路径者相对路径) 第二种通过文件描述符 int fstat(int fdp, struct stat *struct_stat);   *通过文件描述符获取文件对应的属性。fdp为文件描述符 */ struct stat st; /*公共网关接口(Common Gateway Interface,CGI)是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过数据API与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。格式化为HTML文档后,发送给浏览器,也可以将从浏览器获得的数据放到数据库中。*/ int cgi = 0; /* becomes true if server decides this is a CGI * program */ char *query_string = NULL; numchars = get_line(client, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[i]) &amp;&amp; (i &lt; sizeof(method) - 1)) { method[i] = buf[i]; i++; } j=i; method[i] = &#39;\0&#39;; //#include &lt;strings.h&gt; int strcasecmp(cost char*s1,const char* s2); //若参数s1和s2字符串相等则返回0。s1大于s2则返回大于0 的值,s1 小于s2 则返回小于0的值。 if (strcasecmp(method, &quot;GET&quot;) &amp;&amp; strcasecmp(method, &quot;POST&quot;)) { unimplemented(client); return; } //get提交,提交的信息都显示在地址栏中。get提交,对于大数据不行,因为地址栏存储体积有限。 //post提交,提交的信息不显示地址栏中,显示在消息体中。post提交,可以提交大体积数据。 if (strcasecmp(method, &quot;POST&quot;) == 0) cgi = 1; i = 0; while (ISspace(buf[j]) &amp;&amp; (j &lt; numchars)) j++; while (!ISspace(buf[j]) &amp;&amp; (i &lt; sizeof(url) - 1) &amp;&amp; (j &lt; numchars)) { url[i] = buf[j]; i++; j++; } url[i] = &#39;\0&#39;; //strcasecmp忽略大小写比较字符串 if (strcasecmp(method, &quot;GET&quot;) == 0) { query_string = url; while ((*query_string != &#39;?&#39;) &amp;&amp; (*query_string != &#39;\0&#39;)) query_string++; if (*query_string == &#39;?&#39;) { cgi = 0; *query_string = &#39;\0&#39;; query_string++; headers(client, path); while (*query_string != &#39;=&#39;) query_string++; printf(&quot;%s\n&quot;, query_string); query_string++; search_mysql(client, query_string); return; } } sprintf(path, &quot;htdocs%s&quot;, url); if (path[strlen(path) - 1] == &#39;/&#39;) //extern char *strcat(char *dest, const char *src); //把src所指向的字符串(包括&ldquo;\0&rdquo;)复制到dest所指向的字符串后面(删除*dest原来末尾的&ldquo;\0&rdquo;)。 strcat(path, &quot;indexall.html&quot;); //stat返回值: 成功返回0返回-1表示失败 if (stat(path, &amp;st) == -1) { //strcmp不忽略大小写比较字符串 //一直用get_line读取文件,读到http头结束 while ((numchars &gt; 0) &amp;&amp; strcmp(&quot;\n&quot;, buf)) /* read &amp; discard headers */ numchars = get_line(client, buf, sizeof(buf)); not_found(client); } //执行这一步代表读取到了这个文件 else { /* S_IFMT &nbsp; 0170000 &nbsp; 文件类型的位遮罩 &nbsp; S_IFSOCK 0140000 &nbsp; 套接字 &nbsp; S_IFLNK 0120000 &nbsp; &nbsp; 符号连接 &nbsp; S_IFREG 0100000 &nbsp; &nbsp; 一般文件 &nbsp; S_IFBLK 0060000 &nbsp; &nbsp; 区块装置 &nbsp; S_IFDIR 0040000 &nbsp; &nbsp; 目录 &nbsp; S_IFCHR 0020000 &nbsp; &nbsp; 字符装置 &nbsp; S_IFIFO 0010000 &nbsp; &nbsp; 先进先出 ​ &nbsp; S_ISUID 04000 &nbsp; &nbsp; 文件的(set user-id on execution)&nbsp; S_ISGID 02000 &nbsp; &nbsp; 文件的(set group-id on execution)&nbsp; S_ISVTX 01000 &nbsp; &nbsp; 文件的sticky位 ​ &nbsp; S_IRUSR(S_IREAD) 00400 &nbsp; &nbsp; 文件所有者具可读取权限 &nbsp; S_IWUSR(S_IWRITE)00200 &nbsp; &nbsp; 文件所有者具可写入权限 &nbsp; S_IXUSR(S_IEXEC) 00100 &nbsp; &nbsp; 文件所有者具可执行权限 ​ &nbsp; S_IRGRP 00040 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 用户组具可读取权限 &nbsp; S_IWGRP 00020 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 用户组具可写入权限 &nbsp; S_IXGRP 00010 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 用户组具可执行权限 ​ &nbsp; S_IROTH 00004 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 其他用户具可读取权限 &nbsp; S_IWOTH 00002 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 其他用户具可写入权限 &nbsp; S_IXOTH 00001 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 其他用户具可执行权限 */ //是否是文件夹 if ((st.st_mode &amp; S_IFMT) == S_IFDIR) strcat(path, &quot;/myblog.html&quot;); //文件所有者文件所属组其他人 具有可执行权限 if ((st.st_mode &amp; S_IXUSR) || (st.st_mode &amp; S_IXGRP) || (st.st_mode &amp; S_IXOTH) ) cgi = 1; if (!cgi) //执行这一步代表这个文件存在,但是不能执行 //于是就换成读取文件内容再发送 serve_file(client, path); else execute_cgi(client, path, method, query_string); } close(client); }
最新发布
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值