নিরাপদে কোনও ফাইল তৈরি করুন যদি কেবলমাত্র পাইথনের সাথে এটি উপস্থিত না থাকে


94

আমি ফাইলটি ইতিমধ্যে উপস্থিত রয়েছে কি না তার ভিত্তিতে কোনও ফাইলে লিখতে চাই, এটি ইতিমধ্যে উপস্থিত না থাকলে কেবল লেখাই (বাস্তবে, আমি উপস্থিত না থাকা ফাইল খুঁজে না পাওয়া পর্যন্ত আমি ফাইল চেষ্টা করে যেতে চাই))

নিম্নলিখিত কোডটি এমন কোনও উপায় দেখায় যাতে সম্ভাব্য আক্রমণকারী একটি ফাইল এবং ফাইল লেখার জন্য একটি পরীক্ষার মধ্যে এই পোস্টে প্রস্তাবিত হিসাবে একটি সিমিলিংক প্রবেশ করিয়ে দিতে পারে । কোডটি যদি পর্যাপ্ত পর্যায়ে অনুমতি নিয়ে চালানো হয় তবে এটি একটি স্বেচ্ছাসেবী ফাইল ওভাররাইট করতে পারে।

এই সমস্যা সমাধানের জন্য কোনো উপায় আছে কি?

import os
import errno

file_to_be_attacked = 'important_file'

with open(file_to_be_attacked, 'w') as f:
    f.write('Some important content!\n')

test_file = 'testfile'

try:
    with open(test_file) as f: pass
except IOError, e:

    # symlink created here
    os.symlink(file_to_be_attacked, test_file)

    if e.errno != errno.ENOENT:
        raise
    else:
        with open(test_file, 'w') as f:
            f.write('Hello, kthxbye!\n')

পাইথন সঙ্গে পারমাণবিক লেখা চেক করুন stackoverflow.com/questions/2333872/...
Mikko Ohtamaa

@ মিক্কো এটি এখানে সহায়তা করে না।
কনরাড রুডলফ

আহ, ঠিক আছে. আমি বুঝতে পারলাম ব্যাপারটি কী ... ফাইলটি থাকলে আপনি কেবল লেখেন?
মিক্কো ওহতামা

আপনি কি কোনও অস্থায়ী স্থানে ফাইলটি লিখতে পারেন, তারপরে ওভাররাইটের অনুমতি না দিয়ে একটি অনুলিপি কমান্ড করতে পারেন?
এরিক

উত্তর:


95

সম্পাদনা করুন : ডেভ জোন্স এর উত্তরও দেখুন : পাইথন ৩.৩ থেকে আপনি এই ফাংশনটি সরবরাহ করতে xপতাকাটি ব্যবহার করতে পারেন open()

নীচে মূল উত্তর

হ্যাঁ, তবে পাইথনের স্ট্যান্ডার্ড open()কলটি ব্যবহার করা হচ্ছে না । os.open()পরিবর্তে আপনাকে ব্যবহার করতে হবে, যা আপনাকে অন্তর্নিহিত সি কোডে পতাকা নির্দিষ্ট করার অনুমতি দেয়।

বিশেষত, আপনি ব্যবহার করতে চান O_CREAT | O_EXCL। আমার ইউনিক্স সিস্টেমের open(2)অধীনে ম্যান পৃষ্ঠা থেকে O_EXCL:

এই কলটি ফাইলটি তৈরি করেছে তা নিশ্চিত করুন: এই পতাকাটি যদি এর সাথে মিলে নির্দিষ্ট করা থাকে O_CREATএবং পথের নামটি ইতিমধ্যে বিদ্যমান থাকে তবে open()ব্যর্থ হবে। সুনির্দিষ্ট না করা O_EXCLহলে এর আচরণ অপরিজ্ঞাত O_CREAT

যখন এই দুটি পতাকা নির্দিষ্ট করা হয়, প্রতীকী লিঙ্কগুলি অনুসরণ করা হয় না: যদি পথের নামটি একটি প্রতীকী লিঙ্ক হয়, তবে open()প্রতীকী লিঙ্কটি কোথায় চিহ্নিত করবে তা নির্বিশেষে ব্যর্থ হয়।

O_EXCL NFSv3 বা তার পরে কার্নেল ২.6 বা তারপরে ব্যবহার করার সময় কেবলমাত্র এনএফএসে সমর্থিত। এনএফএস O_EXCLসমর্থন সরবরাহ করা হয় না এমন পরিবেশে , লকিং কার্য সম্পাদন করার জন্য যে প্রোগ্রামগুলি এর উপর নির্ভর করে তাদের একটি রেসের শর্ত থাকতে পারে।

সুতরাং এটি নিখুঁত নয়, তবে এএআইএআইএকি এটি এই রেসের শর্তটি এড়াতে আপনার কাছাকাছি যেতে পারে।

সম্পাদনা করুন: প্রয়োগের os.open()পরিবর্তে অন্যান্য নিয়মাবলী open()প্রয়োগ করুন। বিশেষ করে, আপনি পড়া বা লেখা ফিরে ফাইল বর্ণনাকারী ব্যবহার চান, আপনি একটি করতে হবে O_RDONLY, O_WRONLYবা O_RDWRপতাকার পাশাপাশি।

সমস্ত O_*পতাকা পাইথনের osমডিউলে রয়েছে, সুতরাং আপনার প্রয়োজন import osএবং ব্যবহার করতে হবে os.O_CREATইত্যাদি etc.

উদাহরণ:

import os
import errno

flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY

try:
    file_handle = os.open('filename', flags)
except OSError as e:
    if e.errno == errno.EEXIST:  # Failed as the file already exists.
        pass
    else:  # Something unexpected went wrong so reraise the exception.
        raise
else:  # No exception, so the file must have been created successfully.
    with os.fdopen(file_handle, 'w') as file_obj:
        # Using `os.fdopen` converts the handle to an object that acts like a
        # regular Python file object, and the `with` context manager means the
        # file will be automatically closed when we're done with it.
        file_obj.write("Look, ma, I'm writing to a new file!")

4
স্পষ্টতই সঠিক উত্তরের জন্য +1। এনএফএস ক্যাভিয়েটের সাথে প্রকৃতপক্ষে কত লোকের সমস্যা রয়েছে তা জানার জন্য আমি ব্যক্তিগতভাবে আগ্রহী — আমি (সম্ভবত বেপরোয়াভাবে) এটিকে একটি অপ্রচলিত পরিবেশ হিসাবে খারিজ করি যাতে আমার কোডটি কখনও চালানো উচিত নয়।
জিগগ

4
@ জিগগ: এনএফএসভি 3 1995 সালের, সুতরাং পুরানো সংস্করণগুলি অপ্রচলিত হিসাবে বিবেচনা করা মোটামুটি বলে মনে হচ্ছে।
ফ্রেড ফু

4
আমি ব্যক্তিগতভাবে কার্নেল সংস্করণটি সম্পর্কে আরও উদ্বিগ্ন হব। যদি আপনি কোনও আপ-টু-ডেট সিস্টেমের মতো অস্পষ্টভাবে কিছু চালাচ্ছেন তবে আপনার কোনও সমস্যা নেই, তবে আরহেল 3 (এখনও বর্ধিত সমর্থন পর্বে) একটি 2.4 কার্নেল চালাচ্ছেন, উদাহরণস্বরূপ। এছাড়াও, আমি এফএটি বা এনটিএফএসে উইন্ডোজে পারমাণবিক লিখন সরবরাহ করে কিনা তা তদন্ত করে দেখিনি, এটি সম্ভাব্য প্রধান সীমাবদ্ধতা।
আমি_আর

4
@me_and ওপেন ফ্ল্যাগ কনস্ট্যান্টগুলির অজগর পৃষ্ঠাটি পরামর্শ দেয় যে এটি উইন্ডোজের সাথে দুর্দান্ত কাজ করে। আমি শীঘ্রই চেষ্টা করা হবে!
হেনরি গোমারসাল

4
সত্য, তবে আমি কোথাও দেখিনি ( এমএসডিএন সহ ) যা পরিষ্কারভাবে বলেছে যে এই পতাকাগুলি পারমাণবিক ফাইল তৈরি করে। সম্ভবত আমি অত্যধিক ভৌতিক হয়ে পড়ছি, তবে সুরক্ষা-গুরুতর যে কোনও কিছুর জন্য এটি বিশ্বাস করার আগে আমি সেই "পারমাণবিক" কীওয়ার্ডটি দেখতে চাই।
me_ এবং

72

রেফারেন্সের জন্য, পাইথন ৩.৩ এই ব্যবহারের ক্ষেত্রে কভার 'x'করতে open()ফাংশনে একটি নতুন মোড প্রয়োগ করে (কেবল তৈরি করুন, ফাইল উপস্থিত থাকলে ব্যর্থ হন)। নোট করুন যে 'x'মোডটি তার নিজের দ্বারা নির্দিষ্ট করা আছে। অপ্রয়োজনীয় হিসাবে 'wx'ফলাফলগুলি ব্যবহার করা (কলটি সফল হলে কেবলমাত্র আপনি যা করতে পারেন তা ফাইলটিতে লিখতে হবে; কলটি সফল হলে এটি বিদ্যমান থাকতে পারে না):ValueError'w'

>>> f1 = open('new_binary_file', 'xb')
>>> f2 = open('new_text_file', 'x')

পাইথন ৩.২ এবং এর নীচে (পাইথন ২.x সহ) দয়া করে গৃহীত উত্তরটি দেখুন


ভাল পরামর্শ। দুর্ভাগ্যক্রমে এটি কেবল পসিএক্স-হিসাবে দেখা যাচ্ছে (উইন্ডোজে কাজ করে না):Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32 >>> open("c:/temp/foo.csv","wx") ValueError: invalid mode: 'wx'
ড্যান লেন্সকি

5
আপনি পাইথন ৩.২ ব্যবহার করছেন; 'এক্স' মোডটি 3.3 এবং উপরে রয়েছে তবে এটি ক্রস প্ল্যাটফর্ম। ঘটনাক্রমে, আপনি কেবল 'ডাব্লুএক্স'-এর পরিবর্তে' এক্স 'ব্যবহার করেন - ফাইলটি যেভাবেই করতে পারে কেবল তা লেখার মোড অপ্রয়োজনীয়
ডেভ জোনস

পাইথন 3.6:ValueError: must have exactly one of create/read/write/append mode
স্যাজাবলস ডম্বি

4
করবে - যদিও এর পরে আরও কিছুক্ষণ অপেক্ষা করে কম্পিউটারের সামনে না আসা পর্যন্ত অপেক্ষা করতে হবে।
ডেভ জোন্স

4
লেখার জন্য বিদ্যমান ফাইলটি খোলার পক্ষে যুক্তিসঙ্গত, তবে 'x' মোডের পুরো পয়েন্টটি ফাইলটি খোলার আগেই এবং যদি এটি ইতিমধ্যে উপস্থিত না থাকে তবে ফাইলটি উপস্থিত থাকলে ত্রুটিযুক্ত হয়ে ব্যর্থ হয়। এ কারণেই এটি 'ডাব্লু' পতাকাটি দিয়ে অপ্রয়োজনীয়; যদি এটি সফল হয় তবে ফাইলটি খালি থাকার গ্যারান্টিযুক্ত (এবং সুতরাং এটি থেকে খুব কম পয়েন্ট পড়ার দরকার নেই :)।
ডেভ জোন্স

0

এই কোডটি যদি কোনও উপস্থিত না থাকে তবে সহজেই একটি ফাইল তৈরি করবে।

import os
if not os.path.exists('file'):
    open('file', 'w').close() 

16
হ্যা এটা হবে. প্রশ্নটি সম্পর্কে গুরুত্বপূর্ণ বিষয়টি ছিল সুরক্ষা দিক। সমস্যাটি হ'ল ফাইলটির উপস্থিতি সনাক্তকরণ এবং এটি ব্যবহার বা এটি তৈরির মধ্যে কিছু পরিবর্তন হতে পারে যার ফলে খারাপ ফলাফল হয় (মূল প্রশ্নের মতো)।
হেনরি গোমারসাল

5
সেটা সত্য. একে বলা হয় টাকটো!
র‌্যাড

ifবিবৃতি দেওয়ার পরে যদি অন্য কোনও প্রক্রিয়া ফাইল তৈরি করে এবং লেখায় , এই কোডটি ফাইলটি ফাঁকা করে দেবে।
পিটার উড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.