to keep files after kernel rebooting - c

i need to use reboot() system call (to reboot the kernel 2.6.29 with ARM) and i tried the code below:
#include <stdio.h>
#include <linux/reboot.h>
#include <unistd.h>
int main()
{
reboot(LINUX_REBOOT_CMD_RESTART);
}
it works well! but what im wondering is after rebooting the kernel im loosing the files being saved.
i mean if use this code, "url" file is not saved after reboot.
int main()
{
FILE *pFile = fopen("url", "a"); // for .txt file
// write to file/read from file ... etc
fclose(pFile);
int fdUART = open("/dev/ttySAC0", O_RDWR | O_NOCTTY | O_NDELAY);
// some operations on UART port
close(fdUART);
/* Ethernet raw package process*/
/* Char dev driver open and communicate with FPGA fifo */
/* so on */
reboot(LINUX_REBOOT_CMD_RESTART);
}
and am using the UART, Ethernet, char drivers and just would like to know reboot() call systems's effect to my system.
any help highly appreciated thanks.

You've written in the comments that the file system is cramfs.
From the Wikipedia page for cramfs:
The compressed ROM file system (or cramfs) is a free (GPL'ed) read-only Linux file system designed for simplicity and space-efficiency. It is mainly used in embedded systems and small-footprint systems.
Note that it's read-only: that means your changes won't be preserved.
You'll need to write to persistent storage to have your changes preserved.

Related

What happens if you try to read/write a mapping with a deleted / disconnected backing file or device?

If I perform a mmap() on some file or a device in /dev/ that exposes memory, what happens to that mapping if the file is deleted or that device disconnected?
I've written a test program to experiment but I can't find any solid documentation on what should happen. The test program does the following
#include <stdio.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
int fd = open("test_file", O_CREAT | O_RDWR);
uint32_t data[10000] = {0};
data[3] = 22;
write(fd, data, sizeof data);
sync();
struct stat s;
fstat(fd, &s);
uint32_t *map = (uint32_t *)mmap(NULL, s.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
sleep(10);
printf("%u\n", *(map+3));
*(map+9000) = 91;
printf("%u\n", *(map+9000));
return 0;
}
My page size is 4096 bytes so I made the file larger than that so the map would span multiple pages. During that 10s sleep I run the following commands:
$ rm test_file
$ sync; echo 3 > /proc/sys/vm/drop_caches
Which I believe should destroy the backing file of the map and remove all pages so that it must seek the backing file out to perform any operations on it. Then after that 10s sleep the program attempts to read from page 1 and w/r to page 3.
Surprisingly the 2 values I get printed back out are 22 and 91
Why does this happen, is this behavior guaranteed or undefined? Is it because I was using a regular file and not a device? What if the mapping was really large, would things change? Should I expect to get a SIGSEGV or a SIGBUS under some conditions?
rm just unlinks the file from a location in the filesystem (removes it from a directory). If there are other references to the file (such as a process that has it open), the file won't actually be removed -- the OS keeps a reference count of all the references to the file and only deletes it when the reference count drop to 0.
So in this case, the reference count will still be non-zero after the rm as the process has the file open. Only when the files is unmapped and closed (which happens when the process exits) will the file actually be deleted.
In the case of a device, the device file (in the filesystem) is similarly just a reference to the device driver. Removing it won't have any effect. However, if the device itself has some concept of being removed (such as removable storage), doing that will result in future access returning some error.
What happens if you try to read/write a mapping with a deleted ... file
You will still write to that file. rm only unlinks the name from the directory, the file still exists.
disconnected backing ... device?
The process will receive a SIGBUS signal.
Why does this happen, is this behavior guaranteed or undefined?
Guaranteed, files keep reference count since always.
Is it because I was using a regular file and not a device?
No. A device kind of is a regular file. You can open("/dev/sda" and write to it and rm /dev/sda. In Linux almost everything is a regular file. A file has only one more layer of indirection in kernel - a filesystem.
What if the mapping was really large, would things change?
Should I expect to get a SIGSEGV or a SIGBUS under some conditions?
See man mmap. Search for SIGBUS.

Opening USB device for communication in C

The short version. When trying to open a USB device using the open() function in the fcntl.h header, the program freezes
Now the slightly longer version. I am trying to interface with a time of flight sensor (TeraRanger Evo 60m). I am working on a mac running Big Sur 11.2.1. Using ls -l /dev/tty.* i have located the device path to be /dev/tty.usbmodem00000000001A1.
I have taken my code and heavily simplified it to isolate the issue I'm currently facing
#include <fcntl.h> // open
#include <stdio.h> // print
int main()
{
// /dev/tty.usbmodem00000000001A1
char *device = "/dev/tty.usbmodem00000000001A1";
printf("Start\n");
int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);
if(fd < 0)
{
perror(device);
return -1;
}
printf("Opened\n");
return 1;
}
When trying to open the device, the program freezes. There is no error printed to help me debug either. I have successfully connected to and received messages from another USB device I own by only changing the device path. Yet, this sensor make the code freeze.
I may also be useful to know that using the screen /dev/tty.usbmedem00000000001A1 115200 terminal command shows the output expected from the sensor. This means the device is properly functioning and it can be connected to but i have messed up my code somehow. I would greatly appreciate any help y'all can provide. Thank you!

read and write scsi devices file from linux , like sdb,sdc

I want to write my own tag on the device file (scsi file sdb, sdc...) on Linux.
I use linux C open(), read(), write() functions on /dev/sdb file, write my key in this file. But when usb disk device Unplug from computer and plug again, in /dev/sdb's key, sometimes it's gone, or is unstable.
I don't know why.
char readBuf[512] = { 0 };
char key[12] = "h%27dcd*()jd";
int fd = open("/dev/sdb",O_RDWR);
lseek(fd,1024,SEEK_SET);
read(fd,readBuf,512);
for(int i=0; i<sizeof key; ++i)
{
readBuf[i] = ~key[i];
}
lseek(fd,1024,SEEK_SET);
write(fd,readBuf,512);
//In order to mark the Usb disk bear fruit...
for setting a fixed mount point:
you can assign a static mount point (like /dev/sdb) for USB devices using udev rules and a symlink. you can identify the device in the udev rule by i.e. vendor id and product id,...
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="my_device"
https://unix.stackexchange.com/questions/66901/how-to-bind-usb-device-under-a-static-name
for writing bit-wise to specific memory location on the stick:
to write data bytewise to arbitrary blocks on a block device use tools like dd ( https://en.wikipedia.org/wiki/Dd_(Unix) ). file io tools like read(), write() can not be used for writing bytewise WITHOUT using a file...

Why is the Filesystem not recognised?

I 'm trying to print the disk status of my current linux partition.Using the following C code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/statfs.h>
struct statfs S;
int main(int argc,char *argv[]){
int i = statfs("/dev/sda3",&S);
if (i!=0){
printf("File path error!!\n");
exit(0);
}
if(S.f_type == 0xEF53){
printf("The file system is ext_fs");
}
if (S.f_type == 0x4d44)
printf("The Partition is MS DOS super magic\n");
else
printf("Some other partition\n");
printf("Optimum transfer Blocks: %ld\n",S.f_bsize);
return 0;
**The problem is that the line if(S.f_type == 0xEF53) doesn't work correctly i.e. the condition returns false even when i pass /dev/sda4 partition (My linux partition ext4).
I searched a lot but was unable to solve the problem.Please guide me here....
EDIT The value of S.f_type is 16914836
The statfs() system call returns information about a mounted filesystem. path is the pathname of any file within the mounted filesystem.
Instead, you are using it on a device, thus you aren't getting information about it, but about the filesystem where /dev resides (edit: the magic number you reported corresponds to TMPFS_MAGIC, so your /dev is a tmpfs filesystem).
You have to first mount /dev/sda3 (if it's not already mounted) and call statfs over the mountpoint or any file below it to get information about the file system through this syscall.
statfs() returns information about the filesystem containing the file pointed to by its path argument. From statfs(2) manual:
The function statfs() returns information about a mounted filesystem. path is the pathname of any file within the mounted filesystem.
When the first argument is a regular file within the filesystem you wish to interrogate your code works as expected.
I also recommend you use a switch statement and use the constants such as EXT4_SUPER_MAGIC instead of hardcoding values such as 0xEF53.

How to find out if the eth0 mode is static or dhcp?

I want to use a C program to get if the ip of the network interface is set manually or via dhcp.
I've tried to use the following code and it has worked in Debian, but it hasn't worked in OpenWrt. I want to know how to write a C program doing this in OpenWrt.
I have tried to use this:
#include <stdio.h>
int main(void)
{
FILE *fp;
char buffer[80];
fp=popen("cat /etc/network/interfaces |grep ^iface\\ br-lan | awk -F ' ' '{print $4}'","r");
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
pclose(fp);
}
This code is working in Debian, but it isn't working normally in OpenWrt, so I want to know how to write a program to get the same result.
for OpenWRT you can get a such information with the following command:
$uci get network.lan.proto
so I take the program you put in your question and I change only the command used to get information:
#include <stdio.h> <br>
int main(void)
{
FILE *fp;
char buffer[80];
fp=popen("uci get network.lan.proto","r");
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
pclose(fp);
}
to see all network interfaces available in your OpenWRT you can use the following command:
$uci show network
You can avoid using calling linux command in your c by using the libuci. The libuci contains C function to execute uci commands without passing via popen ( popen is used to execute external command from shell).
The libuci exist by default in the development environment of OpenWRT, not need to download it, no need to build it and no need to install it on your OpenWRT machine
You can use libuci in this way
#include <uci.h>
void main()
{
char path[]="network.lan.proto";
char buffer[80];
struct uci_ptr ptr;
struct uci_context *c = uci_alloc_context();
if(!c) return;
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) ||
(ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if(ptr.flags & UCI_LOOKUP_COMPLETE)
strcpy(buffer, ptr.o->v.string);
uci_free_context(c);
printf("%s\n", buffer);
}
(Not tested)
and when you compile your program you have to add the -luci in the compilation command gcc
There's no required way for an OS to decide how an interface should be configured. The kernel (the Linux part of e.g. GNU/Linux) doesn't decide, it doesn't (and shouldn't) care, it just gets told which network addresses go with which interfaces by whatever configuration system the OS is using. OpenWRT's not GNU, it operates differently.
There is AFAIK no definitive way.
Reading the interfaces file would be a hint only: there is no guarantee that the current seup came from there.
You could look at 'asking' the DBUS interface if there is one.
You could check for a dhclient process running.
You could check other files in /etc that specify network setup on different distros.
I think the most reliable option would be a multi-layered thing: check a whole host of hints to come up with the answer.
Another option: send a DHCP check packet to the dhcp server to verify the address.. if you don't get an answer though it could be that the network is down but was up when the address was allocated.

Resources