How do I loop mount programmatically? - mount

I have recently written a guide on how to mount partitions from image files on Raspberry Pi.SE. The instructions are rather complicated and I have a bit of time, so want to replace them by a C program. I have successfully listed the partitions of the image and calculated to appropriate offsets.
In the original instructions, we needed to run
$ sudo mount -o loop,offset=80740352 debian6-19-04-2012.img /mnt
I now need to do this in code. I have found the mount function and libmount in util-linux.
I have now found loopdev.c in util-linux. Is there an easy way to create loop devices or do I have to learn from this code and use ioctl?

The following function binds the loop device device to file at offset. It returns 0 on success, 1 otherwise.
int loopdev_setup_device(const char * file, uint64_t offset, const char * device) {
int file_fd = open(file, O_RDWR);
int device_fd = -1;
struct loop_info64 info;
if(file_fd < 0) {
fprintf(stderr, "Failed to open backing file (%s).\n", file);
goto error;
}
if((device_fd = open(device, O_RDWR)) < 0) {
fprintf(stderr, "Failed to open device (%s).\n", device);
goto error;
}
if(ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) {
fprintf(stderr, "Failed to set fd.\n");
goto error;
}
close(file_fd);
file_fd = -1;
memset(&info, 0, sizeof(struct loop_info64)); /* Is this necessary? */
info.lo_offset = offset;
/* info.lo_sizelimit = 0 => max avilable */
/* info.lo_encrypt_type = 0 => none */
if(ioctl(device_fd, LOOP_SET_STATUS64, &info)) {
fprintf(stderr, "Failed to set info.\n");
goto error;
}
close(device_fd);
device_fd = -1;
return 0;
error:
if(file_fd >= 0) {
close(file_fd);
}
if(device_fd >= 0) {
ioctl(device_fd, LOOP_CLR_FD, 0);
close(device_fd);
}
return 1;
}
References
linux/loop.h
piimg

Related

Downloading Image to a specific folder using gp_filesystem_get_file()

Trying my hands on libgphoto2 library examples and while going through simple-capture.c file. Can i download foo.jpg captured image to a specified folder on my computer?
As far as i understood, in capture_to_file() camera_file_path.folder is the folder in which the file can be found on the camera. So open() should specify the host(computer) location. But nothing worked, i get following error:
You need to specify a folder starting with /store_xxxxxxxxx/
Am i missing something here? Any help would be appreciated, thanks!
I got this working.
Written small application for multiple cameras. Including main() for about question.
int main(int argc, char **argv)
{
CameraList *list;
Camera **cams;
int retval, count, i;
GPContext *context;
FILE *f;
char *data;
unsigned long size;
const char *name, *value;
/*
* Create context
*/
context = sample_create_context();
/*
* Setup Images DB directory.
*/
char* home = getenv("HOME");
if (home == NULL)
{
printf("Error: Unable to fetch home env! \n");
exit(1);
}
char* path = "/Desktop/mw/";
size_t len = strlen(home) + strlen(path) + 1;
char* imgdb = malloc(len);
if (imgdb == NULL)
{
printf("Error: Unable to malloc(). \n");
exit(1);
}
strcpy(imgdb, home);
strcat(imgdb, path);
directory_exists_or_create(imgdb);
/*
* Logs
*/
gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
/*
* Detect all the cameras that can be autodetected
*/
retval = gp_list_new(&list);
if (retval < GP_OK)
{
printf("Unable to create camera list.\n");
return 1;
}
count = sample_autodetect(list, context);
if (count < GP_OK)
{
printf("No cameras detected.\n");
return 1;
}
/*
* Now open all the cameras we autodetected for usage.
*/
printf("Number of cameras: %d\n", count);
cams = calloc(sizeof(Camera*), count);
for (i = 0; i < count; i++)
{
gp_list_get_name(list, i, &name);
gp_list_get_value(list, i, &value);
retval = sample_open_camera(&cams[i], name, value, context);
if (retval < GP_OK)
{
fprintf(stderr, "Camera %s on port %s failed to open\n", name, value);
}
}
if (argc > 0)
{
while ((++argv)[0])
{
if (argv[0][0] == '-')
{
switch (argv[0][1])
{
case 'h':
case 'H':
{
/* Now call a simple function in each of those cameras. */
for (i = 0; i < count; i++)
{
CameraText text;
char *owner;
retval = gp_camera_get_summary (cams[i], &text, context);
if (retval < GP_OK)
{
fprintf (stderr, "Failed to get summary.\n");
continue;
}
gp_list_get_name (list, i, &name);
gp_list_get_value (list, i, &value);
printf("%-30s %-16s\n", name, value);
printf("Summary:\n%s\n", text.text);
/* Query a simple string configuration variable. */
retval = get_config_value_string (cams[i], "owner", &owner, context);
if (retval >= GP_OK)
{
printf("Owner: %s\n", owner);
free (owner);
}
else
{
printf("Owner: No owner found.\n");
}
}
}
/* Graceful exit from the program */
goto exit_;;
default:
printf("Unknown option -%c\n\n", argv[0][1]);
break;
}
}
}
}
/* When I set GP_LOG_DEBUG instead of GP_LOG_ERROR above, I noticed that the
* init function seems to traverse the entire filesystem on the camera. This
* is partly why it takes so long.
* (Marcus: the ptp2 driver does this by default currently.)
*/
printf("Cameras init. Takes about 10 seconds each.\n");
for (i = 0; i < count; i++)
{
retval = gp_camera_init(cams[i], context);
if (retval != GP_OK)
{
printf(" Camera [%d] init failed with retval %d\n", i, retval);
exit (1);
}
}
printf(" ----------------\n");
printf(" Sampler is ready \n");
printf(" ----------------\n");
printf("Usage : \n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
char get_key;
char exit_key = 0;
char bcr_buf[128] = {0};
int hemispheres_counts = 0;
int rotar_steps = 0;
do
{
get_key = getchar();
switch (get_key)
{
// Gracefull Exit
case _ESC_:
exit_key = 1;
break;
// Manual insert mode
case 'i':
case 'I':
printf("ACTION: Type in the name.\n");
scanf("%128s", bcr_buf);
process:
press_enter();
printf("ACTION: Shall we start? press return key.\n");
press_enter();
hemispheres_counts = 0;
rotar_steps = 0;
char product_filename[256] = {0};
strcpy(product_filename, imgdb);
strcat(product_filename, bcr_buf);
if (directory_exists_or_create(product_filename))
{
printf("\n\n!!! ATTENTION: The product already exists !!!\n\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
while (hemispheres_counts < MAX_HEMISPHERES)
{
while (rotar_steps < MAX_ROTAR_STEPS)
{
for (i = 0; i < count; i++)
{
capture_to_memory(cams[i], context, (const char**)&data, &size);
char fname[64] = {0};
char mk_filename[256] = {0};
strcpy(mk_filename, product_filename);
snprintf(fname, sizeof(fname), "/%d-%d-%d.jpg", i, hemispheres_counts, rotar_steps);
strcat(mk_filename, fname);
printf("file name %s\n", mk_filename);
f = fopen(mk_filename, "wb");
if (f)
{
retval = fwrite (data, size, 1, f);
if (retval != size)
{
printf(" fwrite size %ld, written %d\n", size, retval);
}
fclose(f);
}
else
{
printf(" fopen *.jpg failed. %s\n", strerror(errno));
}
usleep(500*1000);
}
rotar_steps++;
}
rotar_steps = 0;
hemispheres_counts++;
if (hemispheres_counts < MAX_HEMISPHERES)
{
printf("Flip the product and hit 'RETURN' key\n");
press_enter(); // This expect some input from user, thats it.
printf("Started capturing other hemisphere!\n");
} else {
printf("Sampling Done for barcode: %s\n", bcr_buf);
printf(" -------------------------------------\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
}
break;
}
} while (exit_key != 1);
exit_:
/*
* Release all the resources.
*/
printf("\nReleasing all the resources ... \n");
for (i = 0; i < count; i++)
{
gp_camera_exit(cams[i], context);
}
if (cams) {
free(cams);
}
free(imgdb);
#if defined(BARCODE_ENABLED)
close_bcr();
#endif
printf("Done.\n");
return 0;
}

Trouble with creating an empty file using C programming language in UNIX environment

I have recently started programming in UNIX environment. I need to write a program which creates an empty file with name and size given in the terminal using this commands
gcc foo.c -o foo.o
./foo.o result.txt 1000
Here result.txt means the name of the newly created file, and 1000 means the size of the file in bytes.
I know for sure that lseek function moves the file offset, but the trouble is that whenever I run the program it creates a file with a given name, however the size of the file is 0.
Here is the code of my small program.
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
int fd;
char *file_name;
off_t bytes;
mode_t mode;
if (argc < 3)
{
perror("There is not enough command-line arguments.");
//return 1;
}
file_name = argv[1];
bytes = atoi(argv[2]);
mode = S_IWUSR | S_IWGRP | S_IWOTH;
if ((fd = creat(file_name, mode)) < 0)
{
perror("File creation error.");
//return 1;
}
if (lseek(fd, bytes, SEEK_SET) == -1)
{
perror("Lseek function error.");
//return 1;
}
close(fd);
return 0;
}
If you aren't allowed to use any other functions to assist in creating a "blank" text file, why not change your file mode on creat() then loop-and-write:
int fd = creat(file_name, 0666);
for (int i=0; i < bytes; i++) {
int wbytes = write(fd, " ", 1);
if (wbytes < 0) {
perror("write error")
return 1;
}
}
You'll want to have some additional checks here but, that would be the general idea.
I don't know whats acceptable in your situation but, possibly adding just the write() call after lseek() even:
// XXX edit to include write
if ((fd = creat(file_name, 0666)) < 0) {
perror("File creation error");
//return 1;
}
// XXX seek to bytes - 1
if (lseek(fd, bytes - 1, SEEK_SET) == -1) {
perror("lseek() error");
//return 1;
}
// add this call to write a single byte # position set by lseek
if (write(fd, " ", 1) == -1) {
perror("write() error");
//return 1;
}
close(fd);
return 0;

Count the running process in AIX by it's name in C

Operating system: IBM AIX 5.3
Compiler: xlc
Hello Everyone
I have a project that using C to process some files using multi-processes. The number of sub-processes are mainly depends on the the number of incoming files and the number of current running processes. I need a reliable method to count on how many sub-processes are running at background.
By comparing the efficiency, directly reading /proc directory may have better performance than invoking popen() to execute $ ps -ef | grep blah.
I wrote a function to read psinfo in /proc/pid/psinfo and compare the arugments.
Pseudo code is as follow:
int count = 0;
dp = opendir("/proc");
while (readdir_r(...))
{
if (dir is not a process)
return -1;
if (dir's owner is not current user)
return -2;
if (failed to open "/proc/[pid]/psinfo")
return -3;
if (failed to read "/proc/[pid]/psinfo")
return -4;
if (process's name matches the given pname)
count += 1;
}
return count;
The function generally runs perfectly at single call. However, it returns -2 or -3 or even wrong counts when embedded in while loop.
The function failed to read the attribute of /proc/pid randomly. It tells No such file or directory.
There is also a small chance to get wrong counts at the end. There seems to be an extra process with certain pid but disappeared when printing the current processes using ps.
I think there is any change were made when reading from sub-directory rapidly after parent directory were being listed.
Is there any thing I made wrong or is there any method to avoid the race condition?
Come extra information about psinfo in AIX
http://www-01.ibm.com/support/knowledgecenter/ssw_aix_53/com.ibm.aix.files/doc/aixfiles/proc.htm%23files-proc?lang=en[233]
Here is the full source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/procfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int countProcess(char *pname)
{
DIR *dir;
int fd;
int pid;
int uid;
int pcounter = 0;
struct psinfo pinfo;
struct dirent entry;
struct dirent *result;
struct stat fsstat;
char path[256];
char process_path[256];
/* Open the /proc directory */
if ((dir = opendir("/proc")) == NULL)
{
return -1;
}
/* Retrieve the current user id */
uid = getuid();
/* Walk through the /proc dir */
for (readdir_r(dir, &entry, &result); result != NULL; readdir_r(dir, &entry, &result))
{
/* See if this is a process, e.g., the dirname is a number
If not, then start off again
*/
if ((pid = atoi(entry.d_name)) == 0)
{
continue;
}
/* Get the attributes of process dir */
snprintf(process_path, sizeof(process_path), "/proc/%s", entry.d_name);
if (stat(process_path, &fsstat) == -1)
{
closedir(dir);
return -2;
}
/* Verify if the process runs by current user
If not, then start off again
*/
if (fsstat.st_uid != uid)
{
continue;
}
/* Open and read from psinfo file */
snprintf(path, sizeof(path), "/proc/%s/psinfo", entry.d_name);
if ((fd = open(path, O_RDONLY)) < 0)
{
close(fd);
closedir(dir);
return -3;
}
if (read(fd, &pinfo, sizeof(pinfo)) < 0)
{
close(fd);
closedir(dir);
return -4;
}
/* String comparison, if same, increase the counter */
if (!strcmp(pinfo.pr_psargs, pname))
{
pcounter++;
}
close(fd);
}
/* returns counter */
closedir(dir);
return pcounter;
}
Update 13/Jan/2015
Thanks to CoreyStup. The race condition can be bypassed by getprocs() function provided in procinfo.h
Here is the code for the solution
#include <stdio.h>
#include <unistd.h>
#include <procinfo.h>
#include <sys/types.h>
int countProcess(const char *pname)
{
struct procsinfo pinfo;
pid_t pid = 0;
uid_t uid;
char args[256];
int index;
int pcounter = 0;
memset(args, 0, sizeof(args));
uid = getuid();
/* Get procsinfo from internal API */
while (0 < getprocs(&pinfo, (int)sizeof(struct procsinfo), NULL, 0, &pid, 1))
{
/* Skip the process that doesn't belong to current user */
if (pinfo.pi_uid != uid)
{
continue;
}
/* Get process arguments */
if (getargs(&pinfo, sizeof(struct procsinfo), args, sizeof(args)) != 0)
{
return -1;
}
/* getargs returns the args list seperated by 0, we need to use space to replace 0 */
for (index = 0; index < 256 - 1 && !(args[index] == 0 && args[index + 1] == 0); index++)
{
if (args[index] == 0)
{
args[index] = ' ';
}
}
if (!strncmp(args, pname, strlen(pname)))
{
pcounter++;
}
}
return pcounter;
}
Try using getprocs(). I find it works better than shelling out with /proc or ps.
I gave an example here: Need help in getting the process name based on the pid in aix

select() message queue failed as bad address(EFAULT) on AIX 6.1.0.0

On AIX 6.1.0.0, select() system call support for message queue, see http://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/select.htm?lang=en
But the below code return failed with errno 14(EFAULT) after select() called:
int msgid = msgget(MQ_KEY, IPC_CREAT|06666);
if (-1 == msgid) {
if (errno != EEXIST) {
ETRACE("msgget() failed: key[%d], errno[%d]", MQ_KEY, errno);
return -1;
}
msgid = msgget(MQ_KEY, 0);
if (-1 == msgid) {
ETRACE("msgget() failed: key[%d], errno[%d]", MQ_KEY, errno);
return -1;
}
}
DTRACE("msgget() success: msgid[%d]", msgid);
/* time out */
struct timeval to;
to.tv_sec = 10;
to.tv_usec = 0;
/* select list */
struct {
int msgids[1];
} rlist, wlist, elist;
rlist.msgids[0] = msgid;
wlist.msgids[0] = msgid;
elist.msgids[0] = msgid;
/* number of list */
int nlist = 1 << 16;
/* int ret = select(nlist, (struct fd_set*)&rlist, (struct fd_set*)&wlist, (struct fd_set*)&elist, &to); */
int ret = select(nlist, (struct fd_set*)&rlist, NULL, NULL, &to);
if (0 == ret) {
WTRACE("select() timeout: ret[%d]", ret);
}
else if (ret < 0) {
ETRACE("select() failed: ret[%d], errno[%d]", ret, errno);
}
else {
ITRACE("select() success");
}
return 0;
Message queue support in select() and poll() is an AIX extension that is no longer enabled by default when compiling on AIX 5.3 and later versions. To enable it, compile with -D_MSGQSUPPORT (or #define _MSGQSUPPORT 1 before the first #include).
It is not mentioned on the select() manual page but the option is mentioned on the poll() manual page, and the same flag enables message queue support for both functions.

Http Streaming from ffmpeg, How to get a sequenced packet?

I am trying to make http streaming program.
So I follow this code at this.
However, when i decode, only one frame is decoded.
I think I need call back function.
Do you know how to make a call back function?
I know 'asf' packet's call back function is like int read_data(void *opaque, char *buf, int buf_size)
But the other formats(mp3, ogg, aac, ..) doesn't work..
Please help me.
Any advice or comment are very appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
int main(int argc, char **argv)
{
static AVInputFormat *file_iformat;
static AVFormatContext *pFormatCtx;
AVFormatParameters params;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
const char url[] = "http://listen.radionomy.com/feelingfloyd";
avcodec_register_all();
avdevice_register_all();
av_register_all();
av_log_set_level(AV_LOG_VERBOSE);
file_iformat = av_find_input_format("mp3"); /* mp3 demuxer */
if (!file_iformat)
{
fprintf(stderr, "Unknown input format: %s\n", &url[0]);
exit(1);
}
//file_iformat->flags |= AVFMT_NOFILE; /* ??? */
params.prealloced_context = 0;
if (av_open_input_file(&pFormatCtx, &url[0], file_iformat, 0, &params) != 0)
{
fprintf(stderr, "err 1\n");
exit(2);
}
/* poulates AVFormatContex structure */
if (av_find_stream_info(pFormatCtx) < 0)
{
fprintf(stderr, "err 2\n");
}
/* sanity check (1 stream) */
if (pFormatCtx->nb_streams != 1 &&
pFormatCtx->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
{
fprintf(stderr, "err 3\n");
}
pCodecCtx = pFormatCtx->streams[0]->codec;
/* find decoder for input audio stream */
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
fprintf(stderr, "err 4: unsupported codec\n");
}
if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
if (avcodec_open(pCodecCtx, pCodec) < 0)
{
fprintf(stderr, "err 5\n");
}
{
uint8_t *pAudioBuffer;
AVPacket pkt;
int ret;
int data_size = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
av_init_packet(&pkt);
//pkt.data=NULL;
//pkt.size=0;
//pkt.stream_index = 0;
pAudioBuffer = av_malloc(data_size * sizeof(int16_t));
while (av_read_frame(pFormatCtx, &pkt) == 0) {
//data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
ret = avcodec_decode_audio3(pFormatCtx->streams[pkt.stream_index]->codec,
(int16_t *)pAudioBuffer, &data_size, &pkt);
/* got an error (-32) here */
if (ret < 0) {
av_strerror(ret, (char *)pAudioBuffer, data_size);
fprintf(stderr, "err 6 (%s)\n", pAudioBuffer);
break;
}
printf("size=%d, stream_index=%d |ret=%d data_size=%d\n",
pkt.size, pkt.stream_index, ret, data_size);
av_free_packet(&pkt);
}
av_free(pAudioBuffer);
}
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
return 0;
}
I figure out this problem by using av_open_input_file.
I got a this problem when I made a iphone app that play http audio streaming. And the above code didn't work. only played just some of audio frame. it also means there are so many buffering.
However After using iphone audio callback function and large audio buffer, it works fine.
Those who are curious about the final code send me a messege.

Resources