I want to get basic information from a hard-drive and print it out. The most important is that the physical sector size is correct.
For the past few hours I have been fighting with ioctl to get what I want but I can't figure it out.
I have never used ioctl before and I can't seem to find an easy explanation on what exactly you have to do.
Anyway my code looks something like this
int main () {
FILE *driveptr;
int sectorsize;
struct hd_driveid hd;
driveptr=fopen("/dev/sda","r");
if (ioctl(driveptr,HDIO_GET_IDENTITY, &hd)!=0) {
printf("Hard disk model: %s\n",hd.model);
printf("Serial number: %s\n",hd.serial_no);
printf("Sector size: %i\n",hd.sector_bytes);
sectorsize=hd.sector_bytes;
} else {
printf("Error fetching device data.\n");
}
}
In the compiler it throws these warnings, it compiles but the strings are empty when printed.
gcc -o test source.c
source.c: In function ‘main’:
source.c:67:9: warning: passing argument 1 of ‘ioctl’ makes integer from pointer without a cast [enabled by default]
/usr/include/x86_64-linux-gnu/sys/ioctl.h:42:12: note: expected ‘int’ but argument is of type ‘struct FILE *’
I hope somebody can explain to me what goes wrong!
Instead of
if (ioctl(driveptr,HDIO_GET_IDENTITY, &hd)!=0) {
you probably want
if (ioctl(fileno(driveptr),HDIO_GET_IDENTITY, &hd)!= -1) {
^^^^^^^ ^ ^^
Because ioctl's first argument need to be an integer file descriptor not a FILE *
fileno() will give you an integer fd from a FILE *.
Note also that ioctl returns -1 on an error and sets errno.
Reading the man pages of the functions you are using is probably quicker than posting to StackOverflow.
See man pages of ioctl, fileno.
Related
So I'm writing a bison (without lex) parser and now I want to read the input code from file and to write the output to another file.
Searching the stackoverflow for some time I found that this way should be good.
bison.y:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern FILE *yyin;
int yylex() { return getc(stdin); }
void yyerror(char *s) {
fprintf (stderr, "%s\n", s);
}
int counter = 1;
char filename2[10] = "dest.ll";
FILE *f2;
%}
%name parse
%%
//grammars
%%
int main(int argc, char *argv[]) {
yyin = fopen(argv[1], "r");
if (argc > 2)
f2 = fopen(argv[2], "w");
else
f2 = fopen(filename2, "w");
yyparse();
return 0;
}
Then i compile it this way:
bison bison.y
cc -ly bison.tab.c
And here the result of cc-compilation:
/tmp/ccNqiuhW.o: In function `main':
bison.tab.c:(.text+0x960): multiple definition of `main'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/liby.a(main.o):(.text.startup+0x0): first defined here
/tmp/ccNqiuhW.o: In function `main':
bison.tab.c:(.text+0x98c): undefined reference to `yyin'
collect2: error: ld returned 1 exit status
The output bison.tab.c file have only 1 main. Ofc int/void main doesn't matter. Can you teach me how to do it correctly?
P.S. By the way, I don't want to spam different posts, and have a little question here. How can I store the string (char *) in $$ in bison? For example, I want to generate a code string after I met the int grammar. I have this error and can't find the answer:
bison.y:94:8: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
INTNUM: NUMBER | DIGIT INTNUM {$$ = "string"};
bison.y: In function ‘yyparse’:
bison.y:28:15: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
PROGRAM: EXPRS { fprintf(f2, "%s: string here %d.\n", $$, counter++) };
will be extremely good if I find the help.
You are linking library liby (linker option -ly). The Bison manual has this to say about it:
The Yacc library contains default implementations of the yyerror and
main functions.
So that's why you have multiple definitions of main. You provide one, and there's one in liby.
Moreover, the docs go on to say that
These default implementations are normally not useful, but POSIX requires them.
(Emphasis added)
You do not need to link liby in order to build a program that includes a bison-generated parser, and normally you should not do so. Instead, provide your own main() and your own yyerror(), both of which you've already done.
Additionally, you are expected to provide a definition of yyin, not just a declaration, whether you link liby or not. To do so, remove the extern keyword from the declaration of yyin in your grammar file.
Your grammar is not complete (there are no rules at all) and the %name directive is not documented and is not recognized by my Bison, but if I add a dummy rule and comment out the %name, in conjunction with the other changes discussed, then bison generates a C source file for me that can be successfully compiled to an executable (without liby).
I am trying to test writing in a file in Contiki. here is the code I used :
#include "contiki.h"
#include <stdio.h>
#define LEN 256
PROCESS(test_process, "Coffee test process");
AUTOSTART_PROCESSES(&test_process);
PROCESS_THREAD(test_process, ev, data)
/**/
{
PROCESS_BEGIN();
FILE * fp;
int i;
/* open the file for writing*/
fp = fopen ("/home/user/contiki/examples/mySim/1.txt","w");
/* write 10 lines of text into the file stream*/
for(i = 0; i < 10;i++){
fprintf (fp, "This is line %d\n",i + 1);
}
/* close the file*/
fclose (fp);
PROCESS_END();
}
I get this error message after compiling in Cooja simulator:
test.c: In function ‘process_thread_test_process’:
test.c:12:1: error: unknown type name ‘FILE’
test.c:15:4: warning: implicit declaration of function ‘fopen’ [-Wimplicit-function-declaration]
test.c:15:7: warning: assignment makes pointer from integer without a cast [enabled by default]
test.c:19:8: warning: implicit declaration of function ‘fprintf’ [-Wimplicit-function-declaration]
test.c:19:8: warning: incompatible implicit declaration of built-in function ‘fprintf’ [enabled by default]
test.c:23:4: warning: implicit declaration of function ‘fclose’ [-Wimplicit-function-declaration]
make: *** [test.co] Error 1
Process returned error code 2
does anyone has any idea about the problem?
Contiki does not provide/support the POSIX file API, the same way it does not have many other things (POSIX sockets API, POSIX process creation and control API). Instead, it provides its own filesystem API ("protosockets" API, "protothreads" API etc.).
There are two filesystem implementations: CFS (Contiki File System) and Coffee. You can use the functions described in the Wiki page; they are analogues to low-level POSIX file API (e.g. cfs_open is similar to POSIX open, cfs_close to POSIX close and so on). There are no analogues for buffered I/O functionality (fopen, fclose) and the FILE structure does not exist.
I just come across this code and the blog says this works fine on 32 bit architecture. I didn't test it; however, I have a doubt about the linkage of libraries in this case. How will the compiler link the string library to main since its not aware which library to link?
So basically if I include <string.h> then it should work fine; however, if I don't include <string.h> then, as per the blog, it runs in 32 bit architecture and fails to run on 64 bit architecture.
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
return errno;
}
printf("file exist\n");
fclose(fp);
return 0;
}
The code shown will only compile if you allow the compiler to infer that functions that are not declared always return an int. This was valid in C89/C90 but marked obsolescent; C99 and C11 require functions to be declared before they are used. GCC prior to version 5.1.0 assumes C90 mode by default; you had to turn the 'reject this code' warnings on. GCC 5.1.0 and onwards assumes C11 by default. You will at least get warnings from the code even without any compilation options to turn them on.
The code will link fine because the function name is strerror() regardless of whether it was declared or not, and the linker can find the function in the standard C library. In general, all the functions that are in the Standard C library are automatically made available for linking — and, indeed, there are usually a lot of not so standard functions also available. C does not have type-safe linkage as C++ does (but C++ also insists on having every function declared before it is used, so the code would not compile as C++ without the header.)
For historical reasons, the maths library was separate and you needed to specify -lm in order to link it. This was in large part because hardware floating point was not universal, so some machines needed a library using the hardware, and other machines needed software emulation of the floating point arithmetic. Some platforms (Linux, for example) still require a separate -lm option if you use functions declared in <math.h> (and probably <tgmath.h>); other platforms (Mac OS X, for example) do not — there is a -lm to satisfy build systems that link it, but the maths functions are in the main C library.
If the code is compiled on a fairly standard 32-bit platform with ILP32 (int, long, pointer all 32-bit), then for many architectures, assuming that strerror() returns an int assumes that it returns the same amount of data as if it returns a char * (which is what strerror() actually returns). So, when the code pushes the return value from strerror() onto the stack for fprintf(), the correct amount of data is pushed.
Note that some architectures (notably the Motorola M680x0 series) would return addresses in an address register (A0) and numbers in a general register (D0), so there would be problems even on those machines with a 32-bit compilation: the compiler would try to get the returned value from the data register instead of the address register, and that was not set by strerror() — leading to chaos.
With a 64-bit architecture (LP64), assuming strerror() returns a 32-bit int means that the compiler will only collect 32-bits of the 64-bit address returned by strerror() and push that on the stack for fprintf() to work with. When it tried to treat the truncated address as valid, things would go awry, often leading to a crash.
When the missing <string.h> header is added, the compiler knows that the strerror() function returns a char * and all is happiness and delight once more, even when the file the program is told to look for doesn't exist.
If you are wise, you will ensure your compiler is always compiling in fussy mode, rejecting anything which is plausibly erroneous. When I use my default compilation on your code, I get:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition bogus.c -o bogus
bogus.c: In function ‘main’:
bogus.c:10:33: error: implicit declaration of function ‘strerror’ [-Werror=implicit-function-declaration]
fprintf(stderr, "%s\n", strerror(errno));
^
bogus.c:10:25: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Werror=format=]
fprintf(stderr, "%s\n", strerror(errno));
^
bogus.c:10:25: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Werror=format=]
bogus.c:4:14: error: unused parameter ‘argc’ [-Werror=unused-parameter]
int main(int argc, char *argv[])
^
cc1: all warnings being treated as errors
$
The 'unused argument' error reminds you that you should be checking that there is an argument to pass to fopen() before you try to open the file.
Fixed code:
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL)
{
fprintf(stderr, "%s: file %s could not be opened for reading: %s\n",
argv[0], argv[1], strerror(errno));
return errno;
}
printf("file %s exists\n", argv[1]);
fclose(fp);
return 0;
}
Build:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition bogus.c -o bogus
$
Run:
$ ./bogus bogus
file bogus exists
$ ./bogus bogus2
./bogus: file bogus2 could not be opened for reading: No such file or directory
$ ./bogus
Usage: ./bogus file
$
Note that the error messages include the program name and report to standard error. When the file is known, the error message includes the file name; it is much easier to debug that error if the program is in a shell script than if the message is just:
No such file or directory
with no indication of which program or which file encountered the problem.
When I remove the #include <string.h> line from the fixed code shown, then I can compile it and run it like this:
$ gcc -o bogus90 bogus.c
bogus.c: In function ‘main’:
bogus.c:18:35: warning: implicit declaration of function ‘strerror’ [-Wimplicit-function-declaration]
argv[0], argv[1], strerror(errno));
^
$ gcc -std=c90 -o bogus90 bogus.c
$ ./bogus90 bogus11
Segmentation fault: 11
$
This was tested with GCC 5.1.0 on Mac OS X 10.10.5 — which is, of course, a 64-bit platform.
I solved with including strings.h header
#include <string.h>
I don't think the functionality of this code would be affected by whether its 32-bit or 64-bit architecture: it doesn't matter if pointers are 32- or 64-bit, and if long int is 32 or 64 bit. Inclusion of headers, in this case string.h, should not affect linking to libraries, either. Header inclusion matters to the compiler, not linker. The compiler might warn about the function being implicitly declared, but as long as the linker can find the function in one of the libraries being searched by it, it will successfully link the binary, and it should run just fine.
I just built and ran this code successfully on a 64-bit CentOS box, using clang 3.6.2. I did get this compiler warning:
junk.c:10:33: warning: implicitly declaring library function 'strerror' with type 'char *(int)'
fprintf(stderr, "%s\n", strerror(errno));
^
junk.c:10:33: note: include the header <string.h> or explicitly provide a declaration for 'strerror'
1 warning generated.
The program was given a non-existent file name, and the error message, "No such file or directory," was meaningful. However, this is because the strerror() function is a well-known standard library function, and its declaration was correctly guessed by the compiler. If it is a user-defined function, the compiler may not be so "lucky" at guessing, and then the architecture can matter, as suggested by other answers.
So, the lesson learned: make sure function declarations are available to the compiler and heed the warnings!
I've searched up and down Google and I cannot find a reason why this code is still failing.
void returnSeven();
int main() {
returnSeven();
return 0;
}
void returnSeven(){
printf("Hello");
}
It builds properly but gives me the
RUN FAILED (exit value 1, total time: 21ms)
error. Any possible ideas how to get rid of this? I've run it from command line and it gives me the same error. I've even had a friend run it and it seemed to work just fine for him. Any ideas would be appreciated.
Your code are ok after adding #include <stdio.h>. So, have you add that line in your code?
In the C programming language, if you haven't define printf, it can also be compiled just with a warning like this : incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
I have to write a program in C which returns file size in blocks just like ls -s command.
Please help.
I tried using stat() function (st_blksize)...And I am unable to implement it.
My code looks like this
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
void main(int argc, char **argv)
{
DIR *dp;
struct dirent *dirp;
struct stat buf;
if(argc < 2)
{
dp = opendir(".");
}
if(dp == NULL)
{
perror("Cannot open directory ");
exit(2);
}
while ((dirp = readdir(dp)) != NULL)
{
printf("%s\n", dirp->d_name);
if (stat(".", &buf))
printf("%d ", buf.st_blksize);
}
closedir(dp);
exit(0);
}
It is giving error buf size is not declared. Don't know what is the problem.
Addition
Thanks for the correction. I included the <sys/stat.h> header file. Now it is giving a warning:
warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__blksize_t’
I am new to C so can't make out what should be the possible solution.
You need to include the correct header:
#incude <sys/stat.h>
That declares the structure and associated functions.
Note that stat() returns zero on success, so your test needs changing (and, as #jsmchmier pointed out in a comment, the call to stat should probably use dirp->d_name rather than the string literal "."). Also, st_blksize is the size of the disk blocks, not the size of the file - that is st_size (measured in bytes).
POSIX says:
off_t st_size For regular files, the file size in bytes.
For symbolic links, the length in bytes of the
pathname contained in the symbolic link.
blksize_t st_blksize A file system-specific preferred I/O block size
for this object. In some file system types, this
may vary from file to file.
blkcnt_t st_blocks Number of blocks allocated for this object.
Note that old (very old) versions of Unix did not support st_blksize or st_blocks. I expect most current versions do.
Now it is giving a warning..warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__blksize_t’
The chances are that __blksize_t is an unisgned integer type similar to size_t. I'd probably use a simple cast:
printf("Block size = %d\n", (int)buf.st_blksize);
Alternatively, if you have C99 available, you could use the facilities from <inttypes.h> to use a bigger size:
printf("Block size = %" PRIu64 "\n", (uint64_t)buf.st_blksize);
In practice, this is overkill; the block size is unlikely to exceed 2 GB this decade, so int is likely to be sufficient for the foreseeable future.
From man 2 stat on my Mac OS X box:
NAME
fstat, fstat64, lstat, lstat64, stat, stat64 -- get file status
SYNOPSIS
#include <sys/stat.h>
int
fstat(int fildes, struct stat *buf);
Note the #include <sys/stat.h> which you have not done. No doubt the actual layout of struct stat is defined in there, which is what your compiler is complaining about.
This is one aspect of the man pages which is not always discussed with beginners but is very useful indeed: the whole unix API is documented in them. Oh, it is not always the easiest place to find a function when you know what it should do but don't know what it is called, but all the answers are there.
Open the file, and stat/fstat it. The struct field st_blocks should contain the information you want. If you're dealing with a directory, use opendir, readdir, closedir (posix)... Just pointers to start your work.
EDIT
Add unistd.h and sys/stat.h. Then remember that stat return 0 on success, so
if (stat(dirp->d_name, &buf) == 0)
and I've changed "." to the name of the "element", which is what you wanted, I suppose. Another change is to use st_blocks and not st_blksize, which says how big is each block (e.g. 1024 or 4096 or...), and -s returns the size in number of blocks, not the size of a block.
The fragment of code is of course incomplete: if you pass an argument, dp is not initialized and even dp == NULL can fail, you shoud have nullified it before:
DIR *dp = NULL;
struct dirent *dirp = NULL;
Careful, one bug in your code is that dp points to garbage and is only initialised if argc is less than 2, but you still try to use it in your while loop and you also try to closedir it. If you invoke your application with any arguments at all, it will probably crash.
To avoid the warning, change the %d to %ld in the line: printf("%d ", buf.st_blksize);