Я работаю над вторым изданием книги Джона Эриксона «Взлом: искусство эксплуатации», используя виртуальную машину (virutalbox) для запуска LiveCD, с которым она поставляется (Ubuntu 7.04). В разделе 0x281 «Доступ к файлам» автор объясняет доступ к файлам через файловые дескрипторы, а также функции open(), close(), read() и write(), используя пример на страницах 82-84.
Код для 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)
Вот строка 105 sys/stat.h:
#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, поэтому какие у вас есть предложения для новичков по изучению и устранению этих проблем в будущем?
Спасибо.
simplenote.c:35: error: 'O-WRONLY' undeclared (first use in this function)
, ноO-WRONLY
(в отличие отO_WRONLY
) не является отдельным символом, поэтому сообщение об ошибке не будет ссылаться на него. Чему еще мы не можем доверять? Вероятно, вам следует явно включить определения POSIX. Добавьте-D_XOPEN_SOURCE=700
в командную строку или#define _XOPEN_SOURCE 700
перед первым#include
и посмотрите, решит ли это что-нибудь. Однако вы не должны сталкиваться с проблемой; заголовок должен быть автономным. - person Jonathan Leffler   schedule 25.07.2015-ansi -pedantic
или-std=c99 -pedantic
). Вы также можете попробовать использовать-std=gnu99
; это может работать лучше. - person Jonathan Leffler   schedule 25.07.2015<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 настолько стар. - person Jonathan Leffler   schedule 26.07.2015st_atim
является новым; он был добавлен в POSIX 2008 (и, следовательно, в POSIX 2013). Раньше было простоst_atime
(аst_atime
теперь макрос дляst_atim.tv_sec
). - person Jonathan Leffler   schedule 26.07.2015-DXOPEN_SOURCE=600
во всех компиляциях и держите пальцы скрещенными; это вполне может решить большинство ваших проблем. Попробуйте также использовать-std=gnu99
или вместо него. Если повезет, один или оба из них помогут вам обойти большинство проблем. Перенесу подборку своих комментариев в ответ. - person Jonathan Leffler   schedule 26.07.2015<fcntl.h>
. Поскольку POSIXopen()
упоминает<sys/stat.h>
как необязательный заголовок, возможно, вам нужно включите его также. На самом деле это не должно быть необходимо, но в вашей косоглазой системе, возможно, это так. Примечание: но вы уже включили оба; может<sys/stat.h>
до<fcntl.h>
? Или, может быть, вам нужна самосогласованная система компиляции. В целом может быть проще. - person Jonathan Leffler   schedule 26.07.2015