Last active
August 29, 2015 14:06
-
-
Save Noitidart/f05ffde7dcaffe792a4d to your computer and use it in GitHub Desktop.
_ff-addon-snippet-LibC_fcntl - Working on getting fcntl to work to detect if profile is locked. (js-ctypes)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cu.import('resource://gre/modules/ctypes.jsm'); | |
Cu.import('resource://gre/modules/osfile.jsm'); | |
function doit() { | |
if (OS.Constants.Sys.Name == 'Darwin') { | |
var _libc = ctypes.open('libc.dylib'); | |
} else if (OS.Constants.Sys.Name == 'Linux') { | |
var _libc = ctypes.open('libc.so.6'); | |
} | |
var lockFilePath = OS.Path.join(OS.Constants.Path.profileDir, '.parentlock'); | |
var lockFilePath = '/Users/noi/Library/Application Support/Firefox/Profiles/6myop6y5.Unnamed Profile 1/.parentlock'; | |
var lockFilePath = '/home/noi/.mozilla/firefox/b51cfon3.Unnamed Profile 1/.parentlock'; //up1 | |
//var lockFilePath = '/home/noi/.mozilla/firefox/eb0nz6yr.Unnamed Profile 2/.parentlock'; //up2 | |
//var lockFilePath = '/home/noi/.mozilla/firefox/qydytdfk.default/.parentlock'; //main | |
//var lockFilePath = '/home/noi/.mozilla/firefox/q0rlb7ap.Unnamed Profile 1/.parentlock'; //dev | |
console.log(lockFilePath); | |
///////////////fcntl | |
if (OS.Constants.Sys.Name == 'Darwin') { | |
var F_GETLK = 7; | |
var F_RDLCK = 1; | |
var F_WRLCK = 3; | |
var F_UNLCK = 2; | |
/* https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fcntl.2.html | |
* struct flock { | |
* off_t l_start; // starting offset | |
* off_t l_len; // len = 0 means until end of file | |
* pid_t l_pid; // lock owner | |
* short l_type; // lock type: read/write, etc. | |
* short l_whence; // type of l_start | |
* }; | |
*/ | |
//order matters: | |
// http://chat.stackexchange.com/transcript/message/17822233#17822233 | |
// https://ask.mozilla.org/question/1134/order-of-strcuture-matters-test-case-flock-for-use-by-fcntl/ | |
var flock = new ctypes.StructType('flock', [ | |
{'l_start': ctypes.unsigned_long}, | |
{'l_len': ctypes.unsigned_long}, | |
{'l_pid': ctypes.int}, | |
{'l_type': ctypes.unsigned_short}, | |
{'l_whence': ctypes.unsigned_short} | |
]); | |
} else if (OS.Constants.Sys.Name == 'Linux') { | |
var F_GETLK = 5; | |
var F_RDLCK = 0; | |
var F_WRLCK = 1; | |
var F_UNLCK = 2; | |
/* http://linux.die.net/man/2/fcntl | |
* typedef struct flock { | |
* ... | |
* short l_type; //Type of lock: F_RDLCK, F_WRLCK, F_UNLCK | |
* short l_whence; //How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END | |
* off_t l_start; //Starting offset for lock | |
* off_t l_len; //Number of bytes to lock | |
* pid_t l_pid; //PID of process blocking our lock (F_GETLK only) | |
* ... | |
* }; | |
*/ | |
//order matters: | |
// http://chat.stackexchange.com/transcript/message/17822233#17822233 | |
// https://ask.mozilla.org/question/1134/order-of-strcuture-matters-test-case-flock-for-use-by-fcntl/ | |
var flock = new ctypes.StructType('flock', [ | |
{'l_type': ctypes.unsigned_short}, | |
{'l_whence': ctypes.unsigned_short}, | |
{'l_start': ctypes.unsigned_long}, | |
{'l_len': ctypes.unsigned_long}, | |
{'l_pid': ctypes.int} | |
]); | |
} | |
//int fcntl(int fd, int cmd, ... /* arg */ ); | |
/* | |
* int fcntl(int fd, int cmd); | |
* int fcntl(int fd, int cmd, long arg); | |
* int fcntl(int fd, int cmd, struct flock *lock); | |
*/ | |
var fcntl = _libc.declare('fcntl', | |
ctypes.default_abi, | |
ctypes.int, | |
ctypes.int, | |
ctypes.int, | |
flock.ptr | |
); | |
//int open(const char *pathname, int flags, mode_t mode); | |
//https://github.com/downthemall/downthemall-mirror/blob/c8fd56c464b2af6b8dc7ddee1f9bbe6e9f6e8382/modules/manager/worker_posix.js#L35 | |
var openFd = _libc.declare( | |
"open", | |
ctypes.default_abi, | |
ctypes.int, // retval | |
ctypes.char.ptr, // path | |
ctypes.int // flags | |
); | |
var closeFd = _libc.declare( | |
"close", | |
ctypes.default_abi, | |
ctypes.int, // retval | |
ctypes.int // fd | |
); | |
var filepath = lockFilePath; | |
//filepath = OS.Path.join(OS.Constants.Path.desktopDir, 'new.txt'); | |
let fd = openFd(filepath, OS.Constants.libc.O_RDWR); //setting this to O_RDWR fixes errno of 9 on fcntl | |
if (fd == -1) { | |
//if file does not exist and O_CREAT was not set. errno is == 2 | |
//if file is a dangling symbolic link. errno is == 2 | |
console.error('failed to open file, fd:', fd, 'errno:', ctypes.errno); | |
return -1; | |
} else { | |
console.log('successfully opened, fd:', fd) | |
} | |
try { | |
var testlock = new flock(); | |
testlock.l_type = F_WRLCK; //can use F_RDLCK but keep openFd at O_RDWR, it just works | |
testlock.l_start = 0; | |
testlock.l_whence = OS.Constants.libc.SEEK_SET; | |
testlock.l_len = 0; | |
var rez = fcntl(fd, F_GETLK, testlock.address()); | |
console.log('rez:', rez); | |
if (rez != -1) { | |
//check testlock.l_type | |
console.log('testlock:', uneval(testlock)); | |
if (testlock.l_type == F_UNLCK) { | |
//can also test if testlock.l_pid is not 0 | |
console.info('file is NOT locked'); | |
} else if (testlock.l_type == F_WRLCK) { | |
console.info('file is WRITE LOCKED, it may be read locked too'); | |
} else if (testlock.l_type == F_RDLCK) { | |
console.info('file is NOT write locked but just READ LOCKED'); //we know this because testlock tested for write lock first | |
} else { | |
console.error('testlock.l_type is unknown, l_type:', testlock.l_type); | |
} | |
} else { | |
console.log('rez was -1, errno', ctypes.errno); | |
} | |
} finally { | |
var rez = closeFd(fd); | |
if (rez == 0) { | |
//console.log('succesfully closed, rez:', rez); | |
} else { | |
console.error('FAILED to close, rez:', rez, 'errno', ctypes.errno); | |
} | |
} | |
} | |
console.time('flock'); | |
doit(); | |
console.timeEnd('flock'); |
for mac, i had to set l_pid
to ctpyes.int
otherwies it would throw ctypes.errno == 22
which is EINVAL
weidr.
Cu.import('resource://gre/modules/ctypes.jsm');
Cu.import('resource://gre/modules/osfile.jsm');
function doit() {
var _libc = ctypes.open('libc.dylib');
//var lockFilePath = OS.Path.join(OS.Constants.Path.profileDir, '.parentlock');
var lockFilePath = '/Users/noi/Library/Application Support/Firefox/Profiles/6myop6y5.Unnamed Profile 1/.parentlock';
//var lockFilePath = '/home/noi/.mozilla/firefox/b51cfon3.Unnamed Profile 1/.parentlock'; //up1
//var lockFilePath = '/home/noi/.mozilla/firefox/eb0nz6yr.Unnamed Profile 2/.parentlock'; //up2
//var lockFilePath = '/home/noi/.mozilla/firefox/qydytdfk.default/.parentlock'; //main
//var lockFilePath = '/home/noi/.mozilla/firefox/q0rlb7ap.Unnamed Profile 1/.parentlock'; //dev
console.log(lockFilePath);
///////////////fcntl
/*
* typedef struct flock {
* ...
* short l_type; //Type of lock: F_RDLCK, F_WRLCK, F_UNLCK
* short l_whence; //How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END
* off_t l_start; //Starting offset for lock
* off_t l_len; //Number of bytes to lock
* pid_t l_pid; //PID of process blocking our lock (F_GETLK only)
* ...
* };
*/
//https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fcntl.2.html
//order matters for mac i guess: http://chat.stackexchange.com/transcript/message/17822233#17822233
var flock = new ctypes.StructType('flock', [
{'l_start': ctypes.unsigned_long},
{'l_len': ctypes.unsigned_long},
{'l_pid': ctypes.int},
{'l_type': ctypes.unsigned_short},
{'l_whence': ctypes.unsigned_short}
]);
//int fcntl(int fd, int cmd, ... /* arg */ );
/*
* int fcntl(int fd, int cmd);
* int fcntl(int fd, int cmd, long arg);
* int fcntl(int fd, int cmd, struct flock *lock);
*/
var fcntl = _libc.declare('fcntl',
ctypes.default_abi,
ctypes.int,
ctypes.int,
ctypes.int,
flock.ptr
);
//int open(const char *pathname, int flags, mode_t mode);
//https://github.com/downthemall/downthemall-mirror/blob/c8fd56c464b2af6b8dc7ddee1f9bbe6e9f6e8382/modules/manager/worker_posix.js#L35
var openFd = _libc.declare(
"open",
ctypes.default_abi,
ctypes.int, // retval
ctypes.char.ptr, // path
ctypes.int // flags
);
var closeFd = _libc.declare(
"close",
ctypes.default_abi,
ctypes.int, // retval
ctypes.int // fd
);
var F_GETLK = 7;
var F_RDLCK = 1;
var F_WRLCK = 3;
var F_UNLCK = 2;
var SEEK_SET = 0;
var SEEK_CUR = 1;
var SEEK_END = 2;
var filepath = lockFilePath;
//filepath = OS.Path.join(OS.Constants.Path.desktopDir, 'new.txt');
var fd = openFd(filepath, OS.Constants.libc.O_RDWR); //setting this to O_RDWR fixes errno of 9 on fcntl
if (fd == -1) {
//if file does not exist and O_CREAT was not set. errno is == 2
//if file is a dangling symbolic link. errno is == 2
console.error('failed to open file, fd:', fd, 'errno:', ctypes.errno);
return -1;
} else {
console.log('successfully opened, fd:', fd)
}
try {
var testlock = new flock();
testlock.l_type = F_WRLCK; //can use F_RDLCK but keep openFd at O_RDWR, it just works
testlock.l_start = 0;
testlock.l_whence = SEEK_SET;
testlock.l_len = 0;
ctypes.errno = 0;
console.log('errno:', ctypes.errno);
var rez = fcntl(fd, F_GETLK, testlock.address());
console.log('rez:', rez);
if (rez != -1) {
//check testlock.l_type
console.log('testlock:', uneval(testlock));
if (testlock.l_type == F_UNLCK) {
//can also test if testlock.l_pid is not 0
console.info('file is NOT locked');
} else if (testlock.l_type == F_WRLCK) {
console.info('file is WRITE LOCKED, it may be read locked too');
} else if (testlock.l_type == F_RDLCK) {
console.info('file is NOT write locked but just READ LOCKED'); //we know this because testlock tested for write lock first
} else {
console.error('testlock.l_type is unknown, l_type:', testlock.l_type);
}
} else {
console.log('rez was -1, errno', ctypes.errno);
}
} finally {
var rez = closeFd(fd);
if (rez == 0) {
//console.log('succesfully closed, rez:', rez);
} else {
console.error('FAILED to close, rez:', rez, 'errno', ctypes.errno);
}
}
}
console.time('flock');
doit();
console.timeEnd('flock');
When using the libc constants follow this commentary to figure out field order:
noida btw guys if short is 2 what is off_t and pid_t?
11:27 noida 8?
11:27 *** avikpal quit (Ping timeout: 121 seconds)
11:27 jdm noida: http://stackoverflow.com/questions/9073667/where-to-find-the-complete-definition-of-off-t-type
11:29 noida so they say blkcnt_t and off_t shall be signed integer types.
11:35 noida jdm in ctypes to get size of platform dependent signed integer do you go ctypes.size_t.size?
11:37 noida ah so maybe harshil__ is on 64bit system thats why he's getting these numbers:
11:37 noida FLOCK_L_LEN:16 L_TYPE:0 L_PID:24 L_WHENCE:2 L_START: 8
11:37 jdm noida: yep, makes sense
11:37 harshil__ yes my os is 64bit
11:37 noida super this is awesome!
11:38 noida so to find offset of field in structure i take that number and divide by size of the type?
11:39 jdm noida: no, you multiply the offset in bytes by *
11:39 jdm er, by 8
11:39 jdm actually I'm not sure what you
11:39 jdm you're asking
11:39 *** Fallen|away is now known as Fallen
11:39 noida these offsets are supposed to help me figure out how to create teh structure
11:40 noida for example in mac flock structure is this:https://gist.github.com/Noitidart/f05ffde7dcaffe792a4d#file-_ff-addon-snippet-fcntl-js-L40
11:40 jdm ah
11:40 noida and in ubuntu the flock structure has the same fields but in different order: see line 67 of that
11:41 jdm so the offset of a field will show how many bytes should have preceded it
11:41 noida oh!!
11:42 jdm if you sort them in ascending order, that's the field order
11:42 jdm and then you sort out the types that will take up that many bytes
11:42 noida ohhh!!!!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
README
Rev1
fcntl
js-ctypes taken from https://github.com/stunts513/gecko/blob/c590fa9853b34f3428707e738a0df0b86d85e3ec/b2g/simulator/packages/subprocess/lib/subprocess.js#L1104Rev2
Rev3
openFd
and changedclose
tocloseFd
, may not needpipe
Rev4
fnctl
is always returning-1
Rev5
errno
just doctypes.errno
and I can set ctypes.errno to anything before running a command and then checking errno for changefcntl
was returning errno of 9 meaning bad file descriptor so need to fix thisRev6
Rev7
O_RDWR
on.open
Rev8
Oh my gosh figured out why it wasn't working.
F_GETLK
was set to wrong constant, I set it to7
(per this guy here and he's wrong!!) it should be5
I figured this out by using the following C code:HOWEVER now the issue is that the order of
flock
matters per OS it looks likeALSO running this code on the
.parentlock
of the file of the current profile always returns that it is NOT locked because it is the same process BUT this is expected behavior, it also matches the behavior ofnsIToolkitProfileService.lockProfilePath
l_pid
field offlock
is not populated with pid when checking.parentlock
of profile running the code from, but obviously if you are running code from a profile you already know the profile is in use. To makefcntl
work right you have to run from other process, so can maybe get it to shell frompopen
or something crap Im guessingRev9
F_RDLCK
,F_WRLCK
, andF_UNLCK
constnats were messed up, and it looks like even the guy that gotF_GETLK
contant right didn't get the these three constants right, I figured them out by using the C code above to dump them.SEEK_*
constants were right.py
and they seem to have their ownfcntl.py
implementation so the constants are different for that reason MAYBEF_RDLCK
right but hisF_GETLK
andF_WRLCK
andF_UNLCK
are not right, but they are commented out so he's probably not using them so probably not accurateRev10
Rev11
l_type
oftestlock
is returned asF_UNLCK
then the file is NOT locked, before it thought it was locked but this was not correctRev12
libc.so.6
)flock
are same based on HEREOS.Constants.libc.SEEK_SET
as I found that was availableRev12
lib.so.6
for mac os too, fixed it toodylib
Rev13