সি-তে ফাইল বর্ণনাকারী থেকে ফাইলের নাম পুনরুদ্ধার করুন


105

সি-তে কোনও ফাইল বর্ণনাকারীর (লিনাক্স) ফাইলের নাম পাওয়া সম্ভব?


আমার ধারণা, বেছে নেওয়া উত্তরটি জিনকে দেওয়া উচিত কারণ তার সমাধানটির আরও ভাল বহনযোগ্যতা রয়েছে এবং অ্যাক্সেসের কোনও উল্লেখযোগ্য সমস্যা নেই।
সের্গেই

এটি উবুন্টু 14.04 (কর্নেল 3.16.0-76-জেনেরিক) এ সমর্থিত নয়। আমি অনুমান করছি এটি লিনাক্সে মোটেই সমর্থিত নয়।
felipou

ম্যাকোস-এর জন্য ডি নাথনেলের আরও একটি প্রশ্নের এই উত্তরটি দেখুন ।
জোনাথন লেফলার

উত্তর:


120

আপনি ব্যবহার করতে পারেন readlinkউপর /proc/self/fd/NNNযেখানে NNN ফাইল বর্ণনাকারী। এটি আপনাকে খোলার সময় ফাইলটির নাম দেবে - তবে, যদি ফাইলটি স্থানান্তরিত বা মুছে ফেলা হয় তবে এটি আর সঠিক হতে পারে না (যদিও লিনাক্স কিছু ক্ষেত্রে নামগুলি ট্র্যাক করতে পারে)। যাচাই করার জন্য, statদেওয়া ফাইলের নাম এবং fstatআপনার কাছে থাকা এফডি, এবং নিশ্চিত করুন st_devএবংst_ino একইরকম।

অবশ্যই, সমস্ত ফাইল বর্ণনাকারী ফাইলগুলিকে উল্লেখ করে না এবং তাদের জন্য আপনি কিছু বিজোড় পাঠ্য স্ট্রিং দেখতে পাবেন, যেমন pipe:[1538488]। যেহেতু সমস্ত আসল ফাইলের নামগুলি পরম পাথ হবে, আপনি এটি নির্ধারণ করতে পারবেন যে এগুলি সহজেই যথেষ্ট। আরও, অন্যরা যেমন উল্লেখ করেছে যে ফাইলগুলিতে একাধিক হার্ডলিঙ্কগুলি তাদেরকে নির্দেশ করতে পারে - এটি কেবল এটির সাথে খোলার প্রতিবেদন করবে। আপনি যদি কোনও প্রদত্ত ফাইলের সমস্ত নাম সন্ধান করতে চান তবে আপনাকে কেবল পুরো ফাইল সিস্টেমটি অতিক্রম করতে হবে।


9
যতক্ষণ না মূল ফাইলটির উল্লেখ রয়েছে (ততক্ষণ একটি খোলা fdযেমন একটি রেফারেন্স হবে), ইনড নম্বরটি পুনরায় ব্যবহার করা যাবে না । ফাইলটি বন্ধ হয়ে যাওয়ার পরে বা এটি খোলার আগে কোনও সফ্টওয়্যার একটি ইনোড নম্বর ব্যবহার করে যা সহজাতভাবে জাতি শর্তের সাপেক্ষে।
আর .. গিটহাব বন্ধ করুন ICE

3
বিপদ, উইল রবিনসন! এটি সর্বদা কার্যকর হয় না --- আপনি যদি setuid()কৌশল করেন তবে /proc/self/fdআপনার প্রক্রিয়াটি অ্যাক্সেসযোগ্য না হওয়া সম্ভব। দেখুন: permalink.gmane.org/gmane.linux.kernel/1302546
ডেভিড

2
@ বিডনলান: এবং ক্ষেত্রে / প্রোক মাউন্ট করা হয়নি?
ব্যবহারকারী 2284570

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

1
@ বিডনলান: নেটবিএসডি সমর্থন / আধিকারিক সমর্থন করে তবে এটি মাউন্ট করা বাধ্যতামূলক নয়। প্রতিবার আমি উল্লেখ করেছি, উত্তরটি "উচ্চতর দামের সরবরাহকারীর দিকে স্যুইচ করুন এবং আপনি / প্রোকে পাবেন"। সুতরাং আমি একটি প্রবিহীন সমাধান খুঁজছি।
ব্যবহারকারী 2284570

90

ম্যাক ওএস এক্সে আমার এই সমস্যাটি ছিল We আমাদের /procভার্চুয়াল ফাইল সিস্টেম নেই, তাই গৃহীত সমাধানটি কাজ করতে পারে না।

পরিবর্তে আমাদের F_GETPATHজন্য একটি আদেশ আছে fcntl:

 F_GETPATH          Get the path of the file descriptor Fildes.  The argu-
                    ment must be a buffer of size MAXPATHLEN or greater.

সুতরাং কোনও ফাইল বর্ণনাকারীর সাথে সম্পর্কিত ফাইলটি পেতে, আপনি এই স্নিপেট ব্যবহার করতে পারেন:

#include <sys/syslimits.h>
#include <fcntl.h>

char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
    // do something with the file path
}

যেহেতু কখনই MAXPATHLENসংজ্ঞায়িত হয় তা আমার মনে নেই, তাই ভেবেছিলাম PATH_MAXসিস্টেমেটস থেকে ভাল হবে।


@ মুচুগাকা, সম্ভবত না। ব্যবহার getsockname
জিনাক

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

2
@ মুচুগাকা হ্যাঁ, সবকিছুই একটি ফাইল, তবে সমস্ত কিছুই ডিরেক্টরি নাম এবং ফাইল সিস্টেমের গাছের ভিতরে অবস্থিত ডিরেক্টরি প্রবেশ নয় । একটি ফাইল একটি ইনোড দ্বারা প্রতিনিধিত্ব করা হয়, এটি কোনও ডিরেক্টরি এন্ট্রি রেফারিং ছাড়া এটি উপস্থিত থাকতে পারে।
দীর্ঘ

9
<Sys / param.h> তে: # ম্যাক্সথ্যালেন পাঠ_ম্যাক্স নির্ধারণ করুন
জিওয়ার

1
আমি কেবল এটি পরীক্ষা করেছি এবং যদি ফাইলটি সরানো হয় এবং আপনি এটি আবার কল করেন তবে এটি সঠিক থাকে (অর্থ: আপনি ফাইলটির নতুন পথ পান)। তবে এটি লিনাক্সে সমর্থিত নয় (উবুন্টু 14.04-এ পরীক্ষিত - F_GETPATH ​​সংজ্ঞায়িত নয়)।
felipou

27

উইন্ডোজ, এটি দিয়ে GetFileInformationByHandleEx , ক্ষণস্থায়ী FileNameInfo , আপনি ফাইলের নাম উদ্ধার করতে পারেন।


17
আমি যতটা উইন্ডোজকে ঘৃণা করি, উইন্ডোগুলির সমতুল্য হ'ল সর্বদা সুন্দর
ম্যাট জেন্ডার

15

টাইলার যেমন উল্লেখ করেছেন, আপনার "প্রত্যক্ষ এবং নির্ভরযোগ্যভাবে" যা প্রয়োজন তা করার কোন উপায় নেই, যেহেতু প্রদত্ত এফডি 0 ফাইলের সাথে (বিভিন্ন ক্ষেত্রে) বা> 1 (একাধিক "হার্ড লিঙ্কগুলি" সম্পর্কিত হতে পারে তবে পরবর্তী পরিস্থিতিটি সাধারণত কীভাবে বর্ণনা করা হয় )। আপনি যদি এখনও (গতি উপর এবং পেয়ে 0, 2, ... ফলাফল বদলে 1 সম্ভাবনা দিকে) সব সীমাবদ্ধতার সঙ্গে কার্যকারিতা প্রয়োজন, এখানে কিভাবে আপনি এটা করতে পারেন: প্রথম, fstat এফডি - এই আপনি বলে , ফলস্বরূপstruct stat , ফাইলটি কোন ডিভাইসে বাস করে, এর মধ্যে কতগুলি হার্ড লিঙ্ক রয়েছে, এটি কোনও বিশেষ ফাইল রয়েছে কিনা ইত্যাদি already এটি ইতিমধ্যে আপনার প্রশ্নের উত্তর দিতে পারে - উদাহরণস্বরূপ যদি 0 হার্ড লিঙ্কগুলি আপনি জানেন তবে বাস্তবে কোনও ফাইলের নাম নেই ডিস্কে

যদি পরিসংখ্যানগুলি আপনাকে প্রত্যাশা দেয়, তবে আপনাকে সমস্ত হার্ড লিঙ্কগুলি না পাওয়া অবধি আপনার প্রাসঙ্গিক ডিভাইসের ডিরেক্টরিতে "গাছের সাথে হাঁটাচলা" করতে হবে (বা কেবলমাত্র প্রথমটি, যদি আপনার একের বেশি প্রয়োজন না হয় এবং যে কোনও একটি করবে না )। যে উদ্দেশ্যে, যদি আপনি ব্যবহার দ্বারা readdir (এবং opendir & অবশ্যই গ) যাও recursively সাবডিরেক্টরি খোলার পর্যন্ত আপনি একটি খুঁজে struct direntএইভাবে পেয়েছি একই inode সংখ্যা আপনি মূল ছিলstruct stat (যা সময়ে গোটা পাথ চান, বরং নাম চেয়ে, এটি পুনর্গঠন করার জন্য আপনাকে ডিরেক্টরিগুলির চেইনটি পিছনের দিকে যেতে হবে)।

যদি এই সাধারণ পদ্ধতির গ্রহণযোগ্য হয় তবে আপনার আরও বিস্তারিত সি কোডের দরকার আছে, আমাদের জানান, এটি লিখতে অসুবিধা হবে না (যদিও এটি অকেজো হয়ে থাকলে আমি এটি লিখি না, অর্থাত্ আপনি অনিবার্যভাবে ধীর পারফরম্যান্স বা প্রতিরোধ করতে পারবেন না) আপনার আবেদনের উদ্দেশ্যে; = 1 ফলাফল পাওয়ার সম্ভাবনা ;-)।


9

এটি অসম্ভব হিসাবে লেখার আগে আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি lsof কমান্ডের উত্স কোডটি দেখুন ।

বিধিনিষেধ থাকতে পারে তবে ফাইল বর্ণনাকারী এবং ফাইলের নাম নির্ধারণে lsof সক্ষম বলে মনে হচ্ছে। এই তথ্যটি / proc ফাইল সিস্টেমে বিদ্যমান তাই আপনার প্রোগ্রাম থেকে পাওয়া সম্ভব হওয়া উচিত।


6

স্ট্রাক স্ট্যাটাস দ্বারা ফাইলের ইনোড পেতে আপনি fstat () ব্যবহার করতে পারেন। তারপরে, রিডডির () ব্যবহার করে আপনি যে ডিরেক্টরি খুঁজে পেয়েছেন তাদের সাথে (স্ট্রাক্ট ডাইরেক্ট) আপনি যে ইনোডটি পেয়েছেন তার সাথে তুলনা করতে পারেন (ধরে নিচ্ছেন যে ডিরেক্টরিটি আপনি জানেন, অন্যথায় আপনাকে পুরো ফাইল সিস্টেমটি অনুসন্ধান করতে হবে) এবং সংশ্লিষ্ট ফাইলটির নামটি সন্ধান করতে পারেন। কদর্য?


2

অসম্ভব। একটি ফাইল বর্ণনাকারীর ফাইল সিস্টেমে একাধিক নাম থাকতে পারে, বা এর কোনও নামই থাকতে পারে।

সম্পাদনা: ধরে নিই যে আপনি কোনও ওএস নির্দিষ্ট না করায় কোনও ওএস-নির্দিষ্ট এপিআই ছাড়াই আপনি একটি সরল পুরাতন পসিক্স সিস্টেমের বিষয়ে কথা বলছেন।


4
তাহলে আমার উত্তর প্রযোজ্য। এটি করার জন্য লিনাক্সের কোনও সুবিধা নেই। লিনাক্স (POSIX) ফাইল বর্ণনাকারীরা অগত্যা ফাইলগুলিকে উল্লেখ করে না এবং এমনকি তারা ফাইলগুলি নাম নয়, তবে ইনোডগুলিও উল্লেখ করে। একটি বিবরণকারী একটি মুছে ফেলা ফাইল (যার ফলে কোনও নাম নেই, এটি টেম্প ফাইলগুলি তৈরি করার একটি সাধারণ উপায়) বা এটি একাধিক নাম (হার্ড লিঙ্কগুলি) সহ একটি ইনোডের দিকে ইঙ্গিত করতে পারে।
টাইলার ম্যাকহেনারি

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

27
লিনাক্স এর জন্য একটি বহনযোগ্য প্যাকযোগ্য এপিআই রয়েছে। প্রকৃতপক্ষে সীমাবদ্ধতা রয়েছে, তবে এটি অসম্ভব বলা কেবল সহজ মিথ্যা।
বিডোনলান

1
@ টাইলার - এলএসফ ইউজারস্পেসে চলে। সুতরাং, এটি ইউজারল্যান্ড কোডে যা কিছু উপলভ্য করে তার জন্য একটি এপিআই রয়েছে :)
বিডনলান

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