Browse Source

Windows bugfixes, including read/write corruption with incog format
Windows test suite runs without errors

philemon 8 years ago
parent
commit
8ab9ae7ea3
8 changed files with 28 additions and 32 deletions
  1. 2 2
      mmgen/filename.py
  2. 4 1
      mmgen/rpc.py
  3. 6 2
      mmgen/seed.py
  4. 6 3
      mmgen/term.py
  5. 2 1
      mmgen/tool.py
  6. 2 2
      mmgen/tx.py
  7. 3 19
      mmgen/util.py
  8. 3 2
      test/test.py

+ 2 - 2
mmgen/filename.py

@@ -48,10 +48,10 @@ class Filename(MMGenObject):
 				die(3,"'%s': not a recognized extension for SeedSource" % self.ext)
 
 
-		# TODO: Check for Windows
-		mode = (os.O_RDONLY,os.O_RDWR)[bool(write)]
 		import stat
 		if stat.S_ISBLK(os.stat(fn).st_mode):
+			mode = (os.O_RDONLY,os.O_RDWR)[bool(write)]
+			if sys.platform[:3] == 'win': mode |= os.O_BINARY
 			try:
 				fd = os.open(fn, mode)
 			except OSError as e:

+ 4 - 1
mmgen/rpc.py

@@ -26,6 +26,8 @@ from mmgen.common import *
 
 class BitcoinRPCConnection(object):
 
+	client_version = 0
+
 	def __init__(
 				self,
 				host='localhost',port=8332,
@@ -79,10 +81,11 @@ class BitcoinRPCConnection(object):
 		dmsg('    RPC POST data ==> %s\n' % p)
 
 		from mmgen.obj import BTCAmt
+		caller = self
 		class MyJSONEncoder(json.JSONEncoder):
 			def default(self, obj):
 				if isinstance(obj, BTCAmt):
-					return str(obj)
+					return (float,str)[caller.client_version>=120000](obj)
 				return json.JSONEncoder.default(self, obj)
 
 #		pp_msg(json.dumps(p,cls=MyJSONEncoder))

+ 6 - 2
mmgen/seed.py

@@ -806,11 +806,13 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 
 	def _format(self):
 		d = self.ssdata
+#		print len(d.iv), len(d.salt), len(d.enc_seed), len(d.wrapper_key)
 		self.fmt_data = d.iv + encrypt_data(
 							d.salt + d.enc_seed,
 							d.wrapper_key,
 							int(hexlify(d.iv),16),
 							self.desc)
+#		print len(self.fmt_data)
 
 	def _filename(self):
 		s = self.seed
@@ -953,7 +955,8 @@ harder to find, you're advised to choose a much larger file size than this.
 		d.target_data_len = self._get_incog_data_len(opt.seed_len)
 		self._check_valid_offset(self.infile,'read')
 
-		fh = os.open(self.infile.name,os.O_RDONLY)
+		flgs = os.O_RDONLY|os.O_BINARY if sys.platform[:3] == 'win' else os.O_RDONLY
+		fh = os.open(self.infile.name,flgs)
 		os.lseek(fh,int(d.hincog_offset),os.SEEK_SET)
 		self.fmt_data = os.read(fh,d.target_data_len)
 		os.close(fh)
@@ -1002,7 +1005,8 @@ harder to find, you're advised to choose a much larger file size than this.
 			self._check_valid_offset(f,'write')
 			if not opt.quiet: confirm_or_exit('',"alter file '%s'" % f.name)
 
-		fh = os.open(f.name,os.O_RDWR)
+		flgs = os.O_RDWR|os.O_BINARY if sys.platform[:3] == 'win' else os.O_RDWR
+		fh = os.open(f.name,flgs)
 		os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
 		os.write(fh, self.fmt_data)
 		os.close(fh)

+ 6 - 3
mmgen/term.py

@@ -224,9 +224,12 @@ def do_pager(text):
 # 'print' instead of the pager.
 # We risk assuming that 'more' will always be available on a stock
 # Windows installation.
-	if sys.platform.startswith('win') and 'HOME' not in environ:
-		shell = True
-		pagers = ['more']
+	if sys.platform.startswith('win'):
+		if 'HOME' not in environ: # native Windows terminal
+			shell = True
+			pagers = ['more']
+		else:                     # MSYS
+			environ['LESS'] = '-cR' # clear screen, disable line chopping
 
 	if 'PAGER' in environ and environ['PAGER'] != pagers[0]:
 		pagers = [environ['PAGER']] + pagers

+ 2 - 1
mmgen/tool.py

@@ -572,7 +572,8 @@ def decrypt(infile,outfile='',hash_preset=''):
 def find_incog_data(filename,iv_id,keep_searching=False):
 	ivsize,bsize,mod = g.aesctr_iv_len,4096,4096*8
 	n,carry = 0,' '*ivsize
-	f = os.open(filename,os.O_RDONLY)
+	flgs = os.O_RDONLY|os.O_BINARY if sys.platform[:3] == 'win' else os.O_RDONLY
+	f = os.open(filename,flgs)
 	for ch in iv_id:
 		if ch not in '0123456789ABCDEF':
 			die(2,"'%s': invalid Incog ID" % iv_id)

+ 2 - 2
mmgen/tx.py

@@ -228,12 +228,12 @@ class MMGenTX(MMGenObject):
 				self.txid,
 				self.send_amt,
 				self.timestamp,
-				(self.blockcount or 'None')
+				self.blockcount
 			),
 			self.hex,
 			repr([e.__dict__ for e in self.inputs]),
 			repr([e.__dict__ for e in self.outputs])
-		) + ((b58encode(self.label),) if self.label else ())
+		) + ((b58encode(self.label.encode('utf8')),) if self.label else ())
 		self.chksum = make_chksum_6(' '.join(lines))
 		self.fmt_data = '\n'.join((self.chksum,) + lines)+'\n'
 

+ 3 - 19
mmgen/util.py

@@ -561,7 +561,6 @@ def get_words(infile,desc,prompt):
 		return get_words_from_user(prompt)
 
 def remove_comments(lines):
-	# re.sub(pattern, repl, string, count=0, flags=0)
 	ret = []
 	for i in lines:
 		i = re.sub(ur'#.*',u'',i,1)
@@ -617,7 +616,6 @@ def get_mmgen_passphrase(desc,passchg=False):
 	else:
 		return ' '.join(get_words_from_user(prompt))
 
-
 def get_bitcoind_passphrase(prompt):
 	if opt.passwd_file:
 		pwfile_reuse_warning()
@@ -626,22 +624,6 @@ def get_bitcoind_passphrase(prompt):
 		return my_raw_input(prompt, echo=opt.echo_passphrase)
 
 
-def check_data_fits_file_at_offset(fname,offset,dlen,action):
-	# TODO: Check for Windows
-	if stat.S_ISBLK(os.stat(fname).st_mode):
-		fd = os.open(fname, os.O_RDONLY)
-		fsize = os.lseek(fd, 0, os.SEEK_END)
-		os.close(fd)
-	else:
-		fsize = os.stat(fname).st_size
-
-	if fsize < offset + dlen:
-		m = ('Input','Destination')[action == 'write']
-		die(1,
-	'%s file has length %s, too short to %s %s bytes of data at offset %s'
-			% (m,fsize,action,dlen,offset))
-
-
 def get_hash_preset_from_user(hp=g.hash_preset,desc='data'):
 	p = """Enter hash preset for %s,
  or hit ENTER to accept the default value ('%s'): """ % (desc,hp)
@@ -766,5 +748,7 @@ def bitcoin_connection():
 	auth_cookie = get_bitcoind_auth_cookie()
 
 	import mmgen.rpc
-	return mmgen.rpc.BitcoinRPCConnection(
+	c = mmgen.rpc.BitcoinRPCConnection(
 				host,port,cfg[user],cfg[passwd],auth_cookie=auth_cookie)
+	c.client_version = int(c.getinfo()['version'])
+	return c

+ 3 - 2
test/test.py

@@ -668,7 +668,8 @@ class MMGenExpect(object):
 		if extra_desc: desc += ' ' + extra_desc
 		for i in cmd_args:
 			if type(i) not in (str,unicode):
-				die(2,'Error: missing input files in cmd line?:\n%s' % cmd_args)
+				fs = 'Error: missing input files in cmd line?:\nName: {}\nCmd: {}\nCmd args: {}'
+				die(2,fs.format(name,mmgen_cmd,cmd_args))
 		cmd_str = mmgen_cmd + ' ' + ' '.join(cmd_args)
 		if opt.log:
 			log_fd.write(cmd_str+'\n')
@@ -1215,7 +1216,7 @@ class MMGenTestSuite(object):
 		add_args = ([],['-q'])[ni]
 		if ni:
 			m = '\nAnswer the interactive prompts as follows:\n' + \
-				" 'y', 'y', 'q', '1-8'<ENTER>, ENTER, ENTER, ENTER, 'y'"
+				" 'y', 'y', 'q', '1-9'<ENTER>, ENTER, ENTER, ENTER, 'y'"
 			msg(grnbg(m))
 		t = MMGenExpect(name,'mmgen-txcreate',['-f','0.0001'] + add_args + cmd_args)
 		if ni: return