0

我正在编写 Jon Erickson 的“黑客:剥削的艺术”的第二版,使用 VM(virutalbox)运行它附带的 LiveCD(Ubuntu 7.04)。在第 0x281 节“文件访问”中,作者使用第 82-84 页上的示例解释了通过文件描述符以及 open() close() read() 和 write() 函数访问文件。

simplenote.c 的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>

void usage(char *prog_name,char *filename){
        printf("Usage: %s < data to add to %s>\n",prog_name,filename);
        exit(0);
}

void fatal(char *);
void *ec_malloc(unsigned int );

int main(int argc,char *argv[]){
        int fd; //file descriptor
        char *buffer,*datafile;

        buffer = (char *)ec_malloc(100);
        datafile = (char *)ec_malloc(20);
        strcpy(datafile,"/tmp/notes");

        if(argc < 2)
                usage(argv[0],datafile);

        strcpy(buffer,argv[1]);

        printf("[DEBUG] buffer   @ %p:\'%s'\n",buffer,buffer);
        printf("[DEBUG] datafile @ %p:\'%s'\n",datafile,datafile);

        strncat(buffer,"\n",1);//Add a newline on the end.

        fd = open(datafile,O_WRONLY|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR);
        if(fd == -1)
                fatal("in main() while opening file");
        printf("[DEBUG] file descriptor is %d\n",fd);
        //Writing data
        if(write(fd,buffer,strlen(buffer)) == -1)
                fatal("in main() while writing buffer to file");
        //Closing file
        if(close(fd) == -1)
                fatal("in main() while closing file");

        printf("Note has been saved.\n");
        free(buffer);
        free(datafile);
}

//A function to display an error message and then exit
void fatal(char *message){
        char error_message[100];

        strcpy(error_message,"[!!]Fatal Error");
        strncat(error_message,message,83);
        perror(error_message);
        exit(-1);
}

//An error-checked malloc() wrapper function 
void *ec_malloc(unsigned int size){
        void *ptr;
        ptr = malloc(size);
        if(ptr == NULL)
                fatal("in ec_malloc() on memory allocation");
        return ptr;
}

但是,当我在终端窗口中键入书中所述的以下说明时,它会返回以下错误消息:

reader@hacking:~/booksrc $ gcc -o simplenote simplenote.c
In file included from /usr/include/sys/stat.h:105, from simplenote.c:6:
/usr/include/bits/stat.h:70: error: field 'st_atim' has incomplete type
/usr/include/bits/stat.h:71: error: field 'st_mtim' has incomplete type
/usr/include/bits/stat.h:72: error: field 'st_ctim' has incomplete type
simplenote.c: In function 'main':
simplenote.c:35: error: 'O-WRONLY' undeclared (first use in this function)
simplenote.c:35: error: (Each undeclared identifier is reported only once
simplenote.c:35: error: for each function it appears in.)
simplenote.c:35: error: 'O_CREAT' undeclared (first use in this function)
simplenote.c:35: error: 'O_APPEND' undeclared (first use in this function)

这是 sys/stat.h 第 105 行:

#include <bits/stat.h>

这里是 bits/stat.h 第 63-83 行:

#ifdef __USE_MISC
    /* Nanosecond resolution timestamps are stored in a format 
       equivalent to 'struct timespec'. This is the type used 
       whenever possible but the Unix namespace rules do not allow the 
       identifier 'timespec' to appear in the <sys/stat.h> header. 
       Therefore we have to handle the use of this header in strictly 
       standard-compliant sources special. */
    struct timespec st_atim;    /* Time of last access. */
    struct timespec st_mtim;    /* Time of last modification. */
    struct timespec st_ctim;    /* Time of last status change. */

# define st_atime st_atim.tv_sec    /* Backward compatibility */
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
#else
    __time_t st_atime;                 /* Time of last access. */
    unsigned long int st_atimensec;    /* Nscecs of last access. */
    __time_t st_mtime;                 /* Time of last modification. */
    unsigned long int st_mtimensec;    /* Nsecs of last modification. */
    __time_t st_ctime;                 /* Time of last status change. */
    unsigned long int st_ctimensec;    /* Nsecs of last status change. */
#endif

我想这可能对第一组问题有一些用处:

C++ 系统文件 bits/stat.h 突然中断,出现“错误:字段 'st_atim' 的类型不完整”

/usr/include/time.h

cat time.h

在我的终端窗口中没有做任何事情。

这是 simplenote.c 的主要功能第 1-6、34-35 行:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>

// Opening the file
    fd = open(datafile, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);

我猜开放函数问题源于 fcntl.h ?

由于作者提供的错误代码,我似乎一直遇到问题。我不想一直依赖 stackoverflow 社区来寻求帮助,那么对于新手在未来检查和解决这些问题有什么建议呢?

谢谢。

4

1 回答 1

0

将选择的评论转换为半连贯的答案。

您可能应该显式启用 POSIX 定义。添加-D_XOPEN_SOURCE=700到命令行,或者#define _XOPEN_SOURCE 700在第一个之前#include,看看是否可以解决任何问题。不过,您不应该遇到问题;标题应该是自包含的。

哦,但是 Ubuntu 7.04 已经过时了……您可能需要使用 600 而不是 700。它是什么时候发布的(这本书什么时候出版的)?如果是 2009 年或更早,您可能需要旧版本 (600)。看到错误仍然令人惊讶。您指定的命令行不包含通常会导致问题的选项(-ansi -pedantic例如,或-std=c99 -pedantic)。您也可以尝试使用-std=gnu99;它可能会更好。

您最近遇到了类似的问题(gcc -o stdlib.h 语法错误 c Hacking the Art of Exploitation)。你解决了吗?听起来好像 Live CD 上的编译系统不是自连贯的,或者您能够使用它的方式意味着它的行为不是自连贯的。你确定编译系统有效吗?它似乎是半失效的。它是否以某种方式使用了错误的标题?

我能够通过插入#include <stdint.h>之前解决以前的问题#include <stdlib.h>

我会尝试-D_XOPEN_SOURCE=600并回复你。编译系统一定有问题。

好吧,您可能需要在 之前包含<time.h>(或可能<sys/time.h><sys/stat.h>,但<sys/stat.h>如果这样做,标题就会被破坏。<stdlib.h>如果在包含<stdint.h>之前必须包含标题,则标题会损坏。我想 Ubuntu 7.04 可能太旧了,以至于您应该#include <sys/types.h>在许多这些标头之前使用,但这仍然不是<stdlib.h>; 那应该是独立的。POSIX 1997#include <sys/types.h>之前需要<sys/stat.h>;POSIX 2004 没有。而且我认为 Ubuntu 7.04 并没有那么老。

但请注意,该st_atim成员是新成员;它被添加到 POSIX 2008(因此在 POSIX 2013 中)。就st_atime在之前(st_atime现在是 的宏st_atim.tv_sec)。

包括-D_XOPEN_SOURCE=600处理过的位统计问题。Ubuntu 7.04 于 2007 年发布,我正在使用的这本书的第二版于 2008 年出版。此外,不确定这是否有用,但在前面的另一个示例中,包括<stdio.h><string.h>(而不是仅<stdio.h>),代码无需任何干预即可正常运行。

有趣……它会让你的生活变得有趣,以一种生活不应该变得有趣的方式。(如“愿你生活在有趣的时代”之类的中国诅咒浮现在脑海中。)-DXOPEN_SOURCE=600在所有汇编中使用该选项并保持手指交叉;这可以很好地解决您的大部分问题。考虑使用-std=gnu99,或者代替。运气好的话,其中一个或两个都可以解决大多数问题。

于 2015-07-26T02:56:33.760 回答