...
 
Commits (29)
......@@ -13,4 +13,11 @@ sysroots
bitbake-logs
camogm
camogm_test
image
all_sources.lst
excluding.lst
including.lst
doxygen.tag
/image
/scripts
/html
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/elphel-apps-camogm/run_bitbake.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/elphel-apps-camogm/scripts/run_bitbake.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="apps-camogm -c target_scp -f"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
......
GUIDIR = camogmgui
PROGS = camogm
TEST_PROG = camogm_test
TEST_PROG = camogm_test
TEST_PROG1 = camogm_fifo_writer
TEST_PROG2 = camogm_fifo_reader
PHPSCRIPTS = camogmstate.php $(GUIDIR)/camogmgui.php $(GUIDIR)/camogmgui.css $(GUIDIR)/camogmgui.js $(GUIDIR)/camogm_interface.php \
$(GUIDIR)/SpryTabbedPanels.css $(GUIDIR)/SpryTabbedPanels.js $(GUIDIR)/xml_simple.php $(GUIDIR)/SpryCollapsiblePanel.css \
$(GUIDIR)/SpryCollapsiblePanel.js
......@@ -11,8 +14,11 @@ IMAGES = $(GUIDIR)/images/filebrowser-01.gif $(GUIDIR)/images/filebrowser-bo
$(GUIDIR)/images/rec_folder.png $(GUIDIR)/images/up_folder.gif $(GUIDIR)/images/play_audio.png $(GUIDIR)/images/hdd.png
SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c
TEST_SRC = camogm_test.c
SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c camogm_align.c
TEST_SRC = camogm_test.c
TEST_SRC1 = camogm_fifo_writer.c
TEST_SRC2 = camogm_fifo_reader.c
OBJS = $(SRCS:.c=.o)
CFLAGS += -Wall -I$(STAGING_DIR_HOST)/usr/include-uapi
......@@ -28,17 +34,21 @@ BINDIR = /usr/bin/
WWW_PAGES = /www/pages
IMAGEDIR = $(WWW_PAGES)/images
all: $(PROGS) $(TEST_PROG)
all: $(PROGS) $(TEST_PROG) $(TEST_PROG1) $(TEST_PROG2)
$(PROGS): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(TEST_PROG): $(TEST_SRC:.c=.o)
$(TEST_PROG): $(TEST_SRC:.c=.o)
$(TEST_PROG1): $(TEST_SRC1:.c=.o)
$(TEST_PROG2): $(TEST_SRC2:.c=.o)
install: $(PROGS) $(PHPSCRIPTS) $(CONFIGS)
$(INSTALL) $(OWN) -d $(DESTDIR)$(BINDIR)
$(INSTALL) $(OWN) -m $(INSTMODE) $(PROGS) $(DESTDIR)$(BINDIR)
$(INSTALL) $(OWN) -m $(INSTMODE) $(TEST_PROG) $(DESTDIR)$(BINDIR)
$(INSTALL) $(OWN) -m $(INSTMODE) $(TEST_PROG1) $(DESTDIR)$(BINDIR)
$(INSTALL) $(OWN) -m $(INSTMODE) $(TEST_PROG2) $(DESTDIR)$(BINDIR)
$(INSTALL) $(OWN) -d $(DESTDIR)$(SYSCONFDIR)
$(INSTALL) $(OWN) -m $(INSTDOCS) $(CONFIGS) $(DESTDIR)$(SYSCONFDIR)
$(INSTALL) $(OWN) -d $(DESTDIR)$(WWW_PAGES)
......
This diff is collapsed.
......@@ -27,7 +27,6 @@
#include <elphel/c313a.h>
#include <elphel/x393_devices.h>
#define CAMOGM_FRAME_NOT_READY 1 ///< frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 ///< invalid frame pointer
#define CAMOGM_FRAME_CHANGED 3 ///< frame parameters have changed
......@@ -38,6 +37,7 @@
#define CAMOGM_TOO_EARLY 8 ///< too early to start, waiting for particular timestamp
#define CAMOGM_FRAME_OTHER 9 ///< other errors
#define CAMOGM_NO_SPACE 10 ///< no free space left on current file system
#define CAMOGM_ERRNUM 11 ///< total number of errors returned, increase this if new error codes are added
#define CAMOGM_FORMAT_NONE 0 ///< no video output
#define CAMOGM_FORMAT_OGM 1 ///< output as Ogg Media file
......@@ -77,6 +77,7 @@ enum state_flags {
STATE_STARTING,
STATE_RUNNING,
STATE_READING,
STATE_RESTARTING,
STATE_CANCEL
};
......@@ -150,6 +151,19 @@ struct writer_params {
int last_ret_val; ///< error value return during last frame recording (if any occurred)
bool exit_thread; ///< flag indicating that the writing thread should terminate
int state; ///< the state of disk writing thread
int segments; ///< the number of segments in frame
struct iovec *data_chunks; ///< a set of vectors pointing to aligned frame data buffers
struct iovec prev_rem_vect; ///< vector pointing to the remainder of the previous frame
unsigned char *rem_buff; ///< buffer containing the unaligned remainder of the current frame
unsigned char *prev_rem_buff; ///< buffer containing the unaligned remainder of the previous frame
unsigned char *common_buff; ///< buffer for aligned JPEG header
uint64_t lba_start; ///< disk starting LBA
uint64_t lba_current; ///< current write position in LBAs
uint64_t lba_end; ///< disk last LBA
time_t stat_update; ///< time when status file was updated
bool dummy_read; ///< inable dummy read cycle (debug feature)
};
/**
* @struct camogm_state
......@@ -242,6 +256,7 @@ typedef struct {
unsigned int active_chn; ///< bitmask of active sensor ports
uint16_t sock_port; ///< command socket port number
struct writer_params writer_params; ///< contains control parameters for writing thread
unsigned int error_stat[SENSOR_PORTS][CAMOGM_ERRNUM]; ///< collect statistics about errors
} camogm_state;
extern int debug_level;
......
This diff is collapsed.
/** @file camogm_align.h
* @brief Provides frame alignment functions use for recording to block device.
* @copyright Copyright (C) 2017 Elphel, Inc.
*
* @par <b>License</b>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CAMOGM_ALIGN_H
#define _CAMOGM_ALIGN_H
#include <unistd.h>
#include <sys/types.h>
#include "camogm.h"
#define PHY_BLOCK_SIZE 512 ///< Physical disk block size
#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker
#define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field
#define INCLUDE_REM 1 ///< Include REM buffer to total size calculation
#define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation
#define MAX_DATA_CHUNKS 9 ///< An array or JPEG frame chunks contains pointers to JPEG leading marker,
///< JPEG header, Exif data if present, stuffing bytes chunk which aligns
///< the frame size to disk sector boundary, JPEG data which
///< can be split into two chunks, align buffers, JPEG
///< trailing marker, and pointer to a buffer containing the remainder of a
///< frame. Nine chunks of data in total.
#define ALIGNMENT_SIZE 32 ///< Align buffers length to this amount of bytes
/** Common buffer should be large enough to contain JPEG header, Exif, some alignment bytes and remainder from previous frame */
#define COMMON_BUFF_SZ MAX_EXIF_SIZE + JPEG_HEADER_MAXSIZE + ALIGNMENT_SIZE + 2 * PHY_BLOCK_SIZE
#define REM_BUFF_SZ 2 * PHY_BLOCK_SIZE
///** This structure holds raw device buffer pointers */
//struct drv_pointers {
// uint64_t lba_start; ///< raw buffer starting LBA
// uint64_t lba_end; ///< raw buffer ending LBA
// uint64_t lba_write; ///< current write pointer inside raw buffer
// uint16_t wr_count; ///< the number of LBA to write next time
//};
/** Container structure for frame buffers */
//struct frame_buffers {
// struct fvec exif_buff; ///< Exif buffer
// struct fvec jpheader_buff; ///< JPEG header buffer
// struct fvec trailer_buff; ///< buffer for trailing marker
// struct fvec common_buff; ///< common buffer where other parts are combined
// struct fvec rem_buff; ///< remainder from previous frame
//};
/** Symbolic names for slots in buffer pointers. Buffer alignment function relies on the order of these names, so
* new names can be added but the overall order should not be changed */
enum {
CHUNK_LEADER, ///< pointer to JPEG leading marker
CHUNK_EXIF, ///< pointer to Exif buffer
CHUNK_HEADER, ///< pointer to JPEG header data excluding leading marker
CHUNK_COMMON, ///< pointer to common buffer
CHUNK_DATA_0, ///< pointer to JPEG data
CHUNK_DATA_1, ///< pointer to the second half of JPEG data if a frame crosses circbuf boundary
CHUNK_TRAILER, ///< pointer to JPEG trailing marker
CHUNK_ALIGN, ///< pointer to buffer where the second part of JPEG data should be aligned
CHUNK_REM ///< pointer to buffer containing the remainder of current frame. It will be recorded during next transaction
};
int init_align_buffers(camogm_state *state);
void deinit_align_buffers(camogm_state *state);
void align_frame(camogm_state *state);
void reset_chunks(struct iovec *vects, int all);
int update_lba(camogm_state *state);
int get_data_buffers(camogm_state *state, struct iovec *mapped, size_t all_sz);
int prep_last_block(camogm_state *state);
off64_t lba_to_offset(uint64_t lba);
#endif /* _CAMOGM_ALIGN_H */
/** @brief This define is needed to use lseek64 and should be set before includes */
#define _LARGEFILE64_SOURCE
/** Needed for O_DIRECT */
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <ctype.h>
#include <sys/uio.h>
#include <poll.h>
// set to 1 second
#define CAMOGM_TIMEOUT 1000
int main(int argc, char *argv[]){
int f_ok;
int ret;
int fer, feo;
long int ftl;
int i=0;
const char pipe_name[] = "/tmp/fifo_test";
int flags;
char cmdbuf[1024];
int fl;
int somecounter = 0;
int writecounter = 0;
FILE *cmd_file;
struct pollfd pfd;
pfd.events = POLLIN;
printf("This is reader. It creates FIFO: %s\n",pipe_name);
// always delete pipe if it exists
f_ok = access(pipe_name, F_OK);
ret = unlink(pipe_name);
if (ret && f_ok == 0) {
printf("Some error\n");
}
ret = mkfifo(pipe_name, 0666); //EEXIST
if (ret) {
if (errno==EEXIST){
printf("Pipe exists\n");
}
}
cmd_file = open(pipe_name, O_RDWR|O_NONBLOCK);
pfd.fd = cmd_file;
fcntl(cmd_file, F_SETFL, 0); /* disable O_NONBLOCK */
printf("Pipe is now open for reading\n");
while(true){
ret = poll(&pfd, 1, CAMOGM_TIMEOUT); /* poll to avoid reading EOF */
somecounter +=1;
if (ret==0) {
printf("TIMEOUT %d\n",somecounter);
}
if (pfd.revents & POLLIN){
printf("PostPoll %d %d, revents = %d, errno = %d\n",somecounter,ret,pfd.revents,errno);
fl = read(cmd_file, cmdbuf, sizeof(cmdbuf));
//clearerr(cmd_file);
if (fl>0) {
writecounter +=1;
}
if (fl<0) {
printf("Error?\n");
break;
}
//fl = read(cmd_file,cmdbuf,sizeof(cmdbuf));
if ((fl>10)||(somecounter>10000000)) {
break;
}
}
}
printf("EXIT! errno=%d writes=%d wdc=%d\n",errno,writecounter,somecounter);
return 0;
}
/** @brief This define is needed to use lseek64 and should be set before includes */
#define _LARGEFILE64_SOURCE
/** Needed for O_DIRECT */
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <ctype.h>
#include <sys/uio.h>
int main(int argc, char *argv[]){
FILE *cmd_file;
const char pipe_name[] = "/tmp/fifo_test";
const char message[] = "test";
int ret;
printf("This is writer\n");
cmd_file = fopen(pipe_name, "w");
while(true){
ret = fwrite(message,sizeof(char),sizeof(message),cmd_file);
printf("Wrote %d bytes, fwrite returned %d\n",sizeof(message),ret);
}
return 0;
}
This diff is collapsed.
......@@ -25,5 +25,6 @@ int camogm_start_jpeg(camogm_state *state);
int camogm_frame_jpeg(camogm_state *state);
int camogm_end_jpeg(camogm_state *state);
void camogm_free_jpeg(camogm_state *state);
int open_state_file(const rawdev_buffer *rawdev, uint64_t *current_pos);
#endif /* _CAMOGM_JPEG_H */
......@@ -1017,8 +1017,8 @@ void *reader(void *arg)
.sockfd_const = &sockfd,
.sockfd_temp = &fd
};
memset(&index_dir, 0, sizeof(struct disk_index));
memset(&index_sparse, 0, sizeof(struct disk_index));
memset(&index_dir, 0, sizeof(struct disk_idir));
memset(&index_sparse, 0, sizeof(struct disk_idir));
prep_socket(&sockfd, state->sock_port);
pthread_cleanup_push(exit_thread, &exit_state);
......
This diff is collapsed.
......@@ -413,7 +413,22 @@ function process_recording(xmldoc) {
var file_name = xmldoc.getElementsByTagName('file_name')[0].firstChild.data;
if (state=='"stopped"'){
clearInterval(update_intvl);
clearTimeout(update_intvl);
} else {
var frame_period = 0;
var rates = xmldoc.getElementsByTagName('frame_period');
for (var i = 0; i < rates.length; i++) {
var data = parseInt(rates[i].firstChild.data);
if (data > frame_period)
frame_period = data;
}
if (frame_period != 0 && frame_period > 1000000) {
frame_period /= 1000;
} else {
frame_period = 1000;
}
clearTimeout(update_intvl);
update_intvl = setTimeout(update_state, frame_period);
}
//Update HTML
document.getElementById('ajax_state').innerHTML = state.substring(1, state.length-1);
......@@ -521,8 +536,8 @@ function toggle_recording() {
document.getElementById('record_text').innerHTML = "<img src=\"images/stop.gif\" style=\"position:relative; bottom:-5px;\"> STOP";
document.getElementById('sitecoloumn').style.backgroundColor = "#AF2020";
clearInterval(update_intvl);
update_intvl = setInterval(update_state,1000);
clearTimeout(update_intvl);
update_intvl = setTimeout(update_state,1000);
}
//update_state();
}
......
#!/usr/bin/env python
# encoding: utf-8
from __future__ import division
from __future__ import print_function
"""
# @file used_files.py
# @brief Extract file access data after build, modify CDT project configuration
# (.cproject) accordingly
# @copyright Copyright (C) 2016, Elphel.inc.
# @param <b>License</b>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
@author: Andrey Filippov
@license: GPLv3.0+
@contact: andrey@elphel.coml
@deffield updated: Updated
"""
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2016, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
import sys
import os
import time
import xml.etree.ElementTree as ET
'''
TODO:Automate, find out why separate touch commands are needed
Run this program twice:
1-st run ./used_files.py linux -1
and save shown timestamp
Then run (some mystery here)
touch src/drivers/ata/ahci_elphel.c
touch src/drivers/elphel/sensor_common.c
Wait 5 seconds and run (in a different console with appropriate sourcing)
bitbake linux-xlnx -c compile -f
Then again
./used_files.py linux <timestamp_from_the_first_run>
If somethong went wrong you will need to resore .cproject from eclipse_project_setup directory
For php:
bitbake php -c cleansstate
bitbake php -c unpack -f
bitbake php -c configure -f
./used_files.py php -1
bitbake php -c compile -f
./used_files.py php 1471044836.8
Doing:
bitbake php -c compile -f
./used_files.py php -1
bitbake php -c compile -f
./used_files.py php 1471044836.8
Corrupts make process
'''
def file_tree(flist): # Each file in list is a file, no directories
ftree={}
for p in flist:
node = ftree
seg_list=p.split(os.sep)
last_i=len(seg_list)-1
for i,segm in enumerate(seg_list):
if not segm in node:
if i == last_i:
node[segm] = None
else:
node[segm] = {}
node=node[segm]
return ftree
def exclude_list(ftree, flist):
mark = "*" # no file/dir name can be "*"
def list_tree_recursive(root):
rslt = []
if not mark in root:
return [[""]] # convert to trailing "/" for directories
for n in root:
if not n == mark:
if root[n] is None:
rslt.append([n])
else:
for l in list_tree_recursive(root[n]):
rslt.append([n]+l)
return rslt
ftree[mark]=None # mark top level dir
for p in flist:
node = ftree
for segm in p.split(os.sep)[:-1]:
node=node[segm]
node[mark]=None # [mark] means used in flist
del node[p.split(os.sep)[-1]]
#print (ftree)
# for k in ftree:
# print(k)
#Now prune unused directories
#prune_recursive(ftree) # (assuming root is used)
# now create list
files_list_list = list_tree_recursive(ftree)
# print (files_list_list)
#converrt to file paths
pl = []
for l in files_list_list:
pl.append(os.path.join(*(l[1:])))
pl = sorted (pl)
return pl
def proc_tree():
DEBUG = True
extensions = [".h",".c",".cpp"]
exclude_start = ["linux"+os.sep+"scripts"+os.sep,"linux"+os.sep+"source"+os.sep+"scripts"+os.sep]
delta_t = 3 # seconds
try:
root_path = sys.argv[1]
except:
print ("Calling %s <root directory path> [timestamp]"%(os.path.basename(sys.argv[0])))
try:
start_time = float(sys.argv[2])
except:
start_time = 0.0
touch_files= start_time < 0.0
print ("root_path = %s"%(root_path))
# root_path = "/home/eyesis/git/poky/linux-elphel/linux/"
lstFiles = []
# Append files to a list
for path, _, files in os.walk(root_path, followlinks = True):
for f in files:
for ext in extensions:
if f.endswith(ext):
lstFiles.append(os.path.join(path, f))
break
all_tree= file_tree(sorted(lstFiles))
include_lst=[]
lst_a = []
latest_at=0
for p in lstFiles:
if touch_files:
if os.path.islink(p):
try:
os.utime(os.path.realpath(p), None)
except:
print("missing linked file: %s"%(os.path.realpath(p)))
else:
os.utime(p, None)
else:
# at = time.ctime(os.stat(p).st_atime)
try:
at = os.stat(p).st_atime
l = None
except:
at = 0
if os.path.islink(p):
try:
l = os.path.realpath(p)
at = os.stat(l).st_atime
except:
at = 0 # missing file
latest_at = max((latest_at,at))
if at > (start_time + delta_t):
#Scripts/lexers result in problems
exclude=False
for exStr in exclude_start:
if p.startswith(exStr):
exclude=True
break
if exclude:
break
#exclude_start
lst_a.append([p,at,l])
include_lst.append(p)
if touch_files:
print (len(lstFiles), "last time = ", time.time())
return
excluding = exclude_list(all_tree, include_lst)
# print (all_tree)
# print (sorted(include_lst))
# print ("|".join(excluding))
if DEBUG:
with open("all_sources.lst","w" ) as f:
for p in sorted(lstFiles):
try:
at = os.stat(p).st_atime
except:
at = 0
lnk=""
if os.path.islink(p):
try:
at = os.stat(os.path.realpath(p)).st_atime
except:
at = 0
lnk = os.path.realpath(p)
print (p,at,lnk, file=f)
with open("excluding.lst","w" ) as f:
for p in excluding:
print (p, file=f)
with open("including.lst","w" ) as f:
for p in include_lst:
print (p, file=f)
# include_tree= file_tree(sorted(include_lst))
# print(include_tree)
root_dir=include_lst[0].split(os.sep)[0]
print ("root_dir=",root_dir)
xml= ET.parse(".cproject")
root=xml.getroot()
# for child in root:
# print(child.tag, child.attrib)
for child in root.iter('sourceEntries'):
for gchild in child:
print(gchild.tag)
for child in root.iter('sourceEntries'):
for gchild in child:
if gchild.tag == 'entry':
attr = gchild.attrib
try:
if (attr['kind'] == 'sourcePath') and (attr['name'] == root_dir):
child.remove (gchild)
print ("Removed existing entry ",gchild.tag)
break
except:
print ("error matching attributes for ",gchild.tag)
pass
break #after first 'sourceEntries' - should be just one?
ET.SubElement(child, 'entry', {"flags":"VALUE_WORKSPACE_PATH", "kind":"sourcePath", "name":root_dir, "excluding":"|".join(excluding)})
for child in root.iter('sourceEntries'):
for gchild in child:
print(gchild.tag)
oneliner= ET.tostring(root)
#overwrites original .cproject, may change to somethong different
with open(".cproject", "wr") as f:
f.write("""<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?>""")
f.write(oneliner)
print (len(lstFiles), len(lst_a), "last access time = ",latest_at)
if __name__ == '__main__':
proc_tree()
"""
make clean # otherwise compiled files are preserved
bitbake apps-autoexposure -c cleansstate
bitbake apps-autoexposure -c unpack -f
bitbake apps-autoexposure -c configure -f
./used_files.py sysroots -1
bitbake apps-autoexposure -c compile -f
./used_files.py sysroots 1473297567.42
eyesis@eyesis-SH87R:~/git/elphel393/rootfs-elphel/elphel-apps-autoexposure$ ./used_files.py sysroots/elphel393/usr -1
root_path = sysroots/elphel393/usr
5615 last time = 1473300068.01
eyesis@eyesis-SH87R:~/git/elphel393/rootfs-elphel/elphel-apps-autoexposure$ ./used_files.py sysroots/elphel393/usr 1473300068.01
root_path = sysroots/elphel393/usr
root_dir= sysroots
entry
entry
entry
entry
entry
5615 84 last access time = 1473300080.1
"""
\ No newline at end of file