I am having a rather strange problem.
I'm trying to open the last modified image with :
std::string exec(string cmd) {
FILE* pipe = popen(cmd.c_str(), "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
if(fgets(buffer, 128, pipe) != NULL)
result = buffer;
pclose(pipe);
result[strlen(result.c_str()) - 1] = '\0';
return result;
}
int main(int argc, char **argv) {
string s = exec("ls ./images -1t | tail -1 &> text.txt");
Mat img = imread(s);
imshow("image", img);
waitKey(0);
return 0;
}
This piece of code works fine. But whenever I rename the file and run this code, the imshow part crashes saying the image has size 0. When I try to print the file name, I get it correct in both cases.
Why is this happening?
Related
I tried to get the return value in the signal handler function, using the longjmp(), but the program return which is not what I expected. Can someone help me? The code is as follows:
void SignalHandler(int sig)
{
longjmp(frameInfo, -2);
}
int main(int argc, char** argv)
{
signal(SIGSEGV, SignalHandler);
if(setjmp(frameInfo) == 0) {
void* ptr = NULL;
int a = *((int *)ptr);
printf("%d\n", a);
return -1;
} else {
printf("in \n"); // printf can work
exit(-2); // or return -2;
}
return 1;
}
I don't know what happened after the printf.
update:
By check assemble code, I see the expected return value.
mov $0xfffffffe,%eax
Compile code and generate a.out, use python or shell check return, ret = 254:
// python
cmd = ./a.out
a = subprocess.Popen(cmd, shell = True)
ret = a.wait()
// shell
./a.out
echo $?
My guess is that after the program returned, the operating system did something special. The question is how do I get the real return value?
So I'm doing the CS50 pset4 recover task (where you need to search for jpg files on a memory card and whenever you find one- you open a new file and write the jpg found to the new file). I have written the code in a slightly different manner then what is told in the course but I think(hope) my logic is right. I am able to recover all 50 images but the images are incomplete and distorted. Also for some reason the 050th image is not opening. Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE; //defining a byte = 8 bits or 8 0's or 1's
int main(int argc, char *argv[]) {
//assigning variables
int BLOCK_SIZE = 512;
BYTE buffer[BLOCK_SIZE];
int i = 0;
char* nf = malloc(sizeof(int)*3);
//checking to see a file name is given
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
//opening said file
FILE *rfile = fopen(argv[1], "r");
if(rfile == NULL)
{
printf("File '%s' does not exist\n", argv[1]);
return 1;
}
//opening a copy
FILE *c = fopen(argv[1], "r");
if(c == NULL)
{
printf("File '%s' does not exist\n", argv[1]);
return 1;
}
//checking 512 bytes again and again for orginal
while (fread (buffer, 1, BLOCK_SIZE, rfile) == BLOCK_SIZE)
{
fseek(c, ftell(rfile) , SEEK_SET); //fread (buffer, 1, BLOCK_SIZE, c);
sprintf(nf, "%03i.jpg", i); //000, 001, 002
//opening a file to write in
FILE *img = fopen(nf, "w");
if(img == NULL)
{
return 1;
}
//Is it a jpeg!?
if (buffer[0]==0xff && buffer[1]==0xd8 && buffer[2]==0xff && (buffer[3] & 0xf0) == 0xe0)
{
//writing the img in a file called img
fwrite(buffer, 512, 1, img);
fwrite(c, BLOCK_SIZE, 2048, img);
i++; //making sure a new file is opened next time
}
fclose(img);
}
fclose(c);
fclose(rfile);
free(nf); }
Why I/O Error causes when I tried ls . command in my fuse filesystem?
My filesystem has a limitation that it only allows mail address type as individual filename and it does not allows sub directory.
Now I want to display a list of file name when use ls . but it does not work.
I understood that it must implement a callback function. (Correspond function is ll_readdir in mycode)
but I have no idea what points are causes the errors.
Update:
Now I use strace command to investigate what system call raise a this error.
According to result of strace, this error caused in getdents64 syscall.
getdents64(3, 0x5611ed000540, 32768) = -1 EIO (Input/output error)
Code1 (implementation of mm:
struct mutex_map {
int counter = 2;
std::mutex _mtx;
std::unordered_map<int, std::string> _data;
std::unordered_map<std::string, int> _rev_data;
public:
int set_value(const char* value) {
std::string s = std::string(value);
std::lock_guard<std::mutex> lock(_mtx);
counter++;
_data[counter] = s;
_rev_data[s] = counter;
return counter;
}
const char* get_value(int key) { return _data[key].c_str(); }
int get_ino(const char* name) { return _rev_data[std::string(name)]; }
};
static mutex_map mm;
Code2: (sendmailfs_stat)
static int sendmailfs_stat(fuse_ino_t ino, struct stat* stbuf,
size_t name_length) {
uid_t uid = getuid();
gid_t gid = getgid();
stbuf->st_ino = ino;
if (ino == 1) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
stbuf->st_uid = uid;
stbuf->st_mode = S_IFDIR;
} else {
stbuf->st_mode = S_IFCHR | 0666;
stbuf->st_nlink = 1;
stbuf->st_size = name_length;
stbuf->st_uid = uid;
stbuf->st_gid = gid;
}
return 0;
}
Code 3: (implementation of readdir callback)
static void ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
struct fuse_file_info* fi) {
// printf("size_t=%ld, fh=%ld, ino=%ld\n", size, fi->fh, ino);
if (ino == 1) {
off_t o = 0;
size_t rest = size;
size_t res;
char* buf = (char*)calloc(1, size);
struct stat dotst;
sendmailfs_stat(ino, &dotst, strlen("."));
res = fuse_add_direntry(req, buf, rest, ".", &dotst, o);
rest -= res;
o++;
printf("%s\n", "start of loop");
uint64_t num_contain = 0;
for (auto& c : mm._data) {
const char* t = c.second.c_str();
int ino2 = mm.get_ino(t);
struct stat st;
sendmailfs_stat(ino2, &st, strlen(t));
fuse_entry_param e;
e.ino = ino2;
e.attr_timeout = 0;
sendmailfs_stat(ino2, &e.attr, strlen(t));
res = fuse_add_direntry_plus(req, buf, rest, t, &e, o);
o += 1;
rest -= res;
}
fuse_reply_buf(req, buf, size);
}
}
A bit late, but if anyone having this error stumbles upon this thread, they might want to check first whether the filesystem is mounted properly. The Input/output error from getdents64 is symptomatic of a filesystem that was unmounted, but failed for some reason (like a file was still in use when user tried the umount command), so still looks mounted, but no data can be fetched from it.
So in this case, some process could be calling umount (and failing) before you run ls, or the filesystem failed to correctly mount in the first place for some reason.
So I am currently attempting recover.c from the cs50 pset3 and I have recovered all 49 jpeg files. However, all these jpeg files are empty (with a grey and white grid). Could someone please explain where my code went wrong? I tried check50 to see if my code was correct but it said the recovered images do not match.
I changed my "w" to "wb" in my fopen function too but that didn't seem to work either.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
int main(int argc, char *argv[])
{
//a data type that can store a byte
typedef uint8_t BYTE;
//Checking to see if there is only one command line argument
if (argc != 2)
{
fprintf(stderr, "Usage: ./recover image\n" );
return 1;
}
//Opening the file to see if its correct
char *infile = argv[1];
FILE *memory = fopen(infile, "r");
if (memory == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 2;
}
//Creation of a buffer
BYTE buffer[512] = {0};
//Whether or not we have found a JPEG or not
bool jpegfound = false;
//the number of JPEG files found
int numJPEGfile = 0;
//declaring the new to be JPEG file so that it has a scope for the
whole while loop
FILE *img = NULL;
//declaring the new JPEG filename
char filename[8];
//Repeating until the end of card
while(fread(buffer, 512, 1, memory) == 1)
{
//Start of a new JPEG?
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
jpegfound = true;
sprintf(filename, "%03i.jpg", numJPEGfile);
numJPEGfile += 1;
img = fopen(filename, "wb");
fwrite(buffer, 512, 1, img);
}
//Have we already found a JPEG?
if(jpegfound)
{
jpegfound = false;
fclose(img);
}
}
//Close any remaining files
fclose(memory);
return 0;
}
If you run the below command in the terminal, how large are the jpg-files you recovered? I think this will give you a hint for solving this pset.
ls -l
I would like to implement a main function such as in order to execute system commands. The following code is currently used :
int main(int argc, char *argv[])
{
size_t cmd_length;
char *cmd_buffer = NULL;
char *file = NULL;
char *ip = NULL;
int size;
if(argc == 3)
{
size = strlen(argv[1]);
file = (char*)malloc((size + 1)*sizeof(char));
strcpy(file, argv[1]);
size = strlen(argv[2]);
ip = (char*)malloc((size + 1)*sizeof(char));
strcpy(ip, argv[2]);
}
cmd_length = snprintf(NULL, 0, "tftp -g -r %s %s", file, ip);
cmd_buffer = malloc(cmd_length + 1);
if (cmd_buffer == NULL)
{
return -1;
}
snprintf(cmd_buffer, cmd_length + 1, "tftp -g -r %s %s", file, ip);
if(system(cmd_buffer) == 0)
{
then ...
}
{
return -1;
}
free(cmd_buffer);
cmd_buffer = NULL;
cmd_length = snprintf(NULL, 0, "tftp -g -r %s %s", DFT_FILE, DFT_IP);
cmd_buffer = malloc(cmd_length + 1);
if (cmd_buffer == NULL)
{
return -1;
}
snprintf(cmd_buffer, cmd_length + 1, "tftp -g -r %s %s", DFT_FILE, DFT_IP);
if(system(cmd_buffer) == 0)
{
then ...
}
{
return -1;
}
free(cmd_buffer);
free(file);
free(ip);
cmd_buffer = NULL;
file = NULL;
ip = NULL;
return 0;
}
Because I need to enter other commands, I am currently using the same cmd_buffer by using free() before reallocating memory. Is it the right way to do ? Some other commands might be required in the future.
Your program can be be greatly simplified if you use a common function to execute the system call. It doesn't even need to use malloc at all. Here's a partial implementation [Please pardon the gratuitous style cleanup]:
#include <stdarg.h>
int
execute_command(const char *fmt,...)
{
char cmd_buffer[5000];
int cmd_length;
va_list ap;
// NOTE: much simpler to used a fixed size buffer that is larger than
// needed
va_start(ap,fmt);
cmd_length = vsnprintf(cmd_buffer,sizeof(cmd_buffer),fmt,ap);
va_end(ap);
if (system(cmd_buffer) != 0)
return -1;
return 0;
}
int
main(int argc, char *argv[])
{
char *file = NULL;
char *ip = NULL;
// NOTE: I had to guess the intent if fewer arguments are passed (e.g. just
// skip as I did here, print message and abort?)
if (argc == 3) {
// NOTE: no need to malloc these, but if you did, see strdup(3)
file = argv[1];
ip = argv[2];
execute_command("tftp -g -r %s %s", file, ip);
}
execute_command("tftp -g -r %s %s", DFT_FILE, DFT_IP);
return 0;
}
Yes, you are essentially just re-using the pointer variable cmd_buffer which is fine. And for every malloc() there is a matching free(), which is good.
You should factor our common code into a function, for example runCommand(const char *command, ...) (using varargs).