Saturday, November 3, 2007


PATH_MAX simply isn't



Many C/C++ programmers at some point may run into a limit known as PATH_MAX. Basically, if you have to keep track of paths to files/directories, how big does your buffer have to be?
Most Operating Systems/File Systems I've seen, limit a filename or any particular path component to 255 bytes or so. But a full path is a different matter.

Many programmers will immediately tell you that if your buffer is PATH_MAX, or PATH_MAX+1 bytes, it's long enough. A good C++ programmer of course would use C++ strings (std::string or similar with a particular API) to avoid any buffer length issues. But even when having dynamic strings in your program taking care of the nitty gritty issue of how long your buffers need to be, they only solve half the problem.

Even a C++ programmer may at some point want to call the getcwd() or realpath() (fullpath() on Windows) functions, which take a pointer to a writable buffer, and not a C++ string, and according to the standard, they don't do their own allocation. Even ones that do their own allocation very often just allocate PATH_MAX bytes.

getcwd() is a function to return what the current working directory is. realpath() can take a relative or absolute path to any filename, containing .. or levels of /././. or extra slashes, and symlinks and the like, and return a full absolute path without any extra garbage. These functions have a flaw though.

The flaw is that PATH_MAX simply isn't. Each system can define PATH_MAX to whatever size it likes. On my Linux system, I see it's 4096, on my OpenBSD system, I see it's 1024, on Windows, it's 260.

Now performing a test on my Linux system, I noticed that it limits a path component to 255 characters on ext3, but it doesn't stop me from making as many nested ones as I like. I successfully created a path 6000 characters long. Linux does absolutely nothing to stop me from creating such a large path, nor from mounting one large path on another. Running getcwd() in such a large path, even with a huge buffer, fails, since it doesn't work with anything past PATH_MAX.

Even a commercial OS like Mac OS X defines it as 1024, but tests show you can create a path several thousand characters long. Interestingly enough, OSX's getcwd() will properly identify a path which is larger than its PATH_MAX if you pass it a large enough buffer with enough room to hold all the data. This is possible, because the prototype for getcwd() is:
char *getcwd(char *buf, size_t size);


So a smart getcwd() can work if there's enough room. But unfortunately, there is no way to determine how much space you actually need, so you can't allocate it in advance. You'd have to keep allocating larger and larger buffers hoping one of them will finally work, which is quite retarded.

Since a path can be longer than PATH_MAX, the define is useless, writing code based off of it is wrong, and the functions that require it are broken.

An exception to this is Windows. It doesn't allow any paths to be created larger than 260 characters. If the path was created on a partition from a different OS, Windows won't allow anything to access it. It sounds strange that such a small limit was chosen, considering that FAT has no such limit imposed, and NTFS allows paths to be 32768 characters long. I can easily imagine someone with a sizable audio collection having a 300+ character path like so:
"C:\Documents and Settings\Jonathan Ezekiel Cornflour\My Documents\My Music\My Personal Rips\2007\Technological\Operating System Symphony Orchestra\The GNOME Musical Men\I Married Her For Her File System\You Don't Appreciate Marriage Until You've Noticed Tax Pro's Wizard For Married Couples.Track 01.MP5"


Before we forget, here's the prototype for realpath:
char *realpath(const char *file_name, char *resolved_name);


Now looking at that prototype, you should immediately say to yourself, but where's the size value for resolved_name? We don't want a buffer overflow! Which is why OSs will implement it based on the PATH_MAX define.
The resolved_name argument must refer to a buffer capable of storing at least PATH_MAX characters.

Which basically means, it can never work on a large path, and no clever OS can implement around it, unless it actually checks how much RAM is allocated on that pointer using an OS specific method - if available.

For these reasons, I've decided to implement getcwd() and realpath() myself. We'll discuss the exact specifics of realpath() next time, for now however, we will focus on how one can make their own getcwd().

The idea is to walk up the tree from the working directory, till we reach the root, along the way noting which path component we just went across.
Every modern OS has a stat() function which can take a path component and return information about it, such as when it was created, which device it is located on, and the like. All these OSs except for Windows return the fields st_dev and st_ino which together can uniquely identify any file or directory. If those two fields match the data retrieved in some other way on the same system, you can be sure they're the same file/directory.
To start, we'd determine the unique ID for . and /, once we have those, we can construct our loop. At each step, when the current doesn't equal the root, we can change directory to .., then scan the directory (using opendir()+readdir()+closedir()) for a component with the same ID. Once a matching ID is found, we can denote that as the correct name for the current level, and move up one.

Code demonstrating this in C++ is as follows:


bool getcwd(std::string& path)
{
typedef std::pair<dev_t, ino_t> file_id;

bool success = false;
int start_fd = open(".", O_RDONLY); //Keep track of start directory, so can jump back to it later
if (start_fd != -1)
{
struct stat sb;
if (!fstat(start_fd, &sb))
{
file_id current_id(sb.st_dev, sb.st_ino);
if (!stat("/", &sb)) //Get info for root directory, so we can determine when we hit it
{
std::vector<std::string> path_components;
file_id root_id(sb.st_dev, sb.st_ino);

while (current_id != root_id) //If they're equal, we've obtained enough info to build the path
{
bool pushed = false;

if (!chdir("..")) //Keep recursing towards root each iteration
{
DIR *dir = opendir(".");
if (dir)
{
dirent *entry;
while ((entry = readdir(dir))) //We loop through each entry trying to find where we came from
{
if ((strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..") && !lstat(entry->d_name, &sb)))
{
file_id child_id(sb.st_dev, sb.st_ino);
if (child_id == current_id) //We found where we came from, add its name to the list
{
path_components.push_back(entry->d_name);
pushed = true;
break;
}
}
}
closedir(dir);

if (pushed && !stat(".", &sb)) //If we have a reason to contiue, we update the current dir id
{
current_id = file_id(sb.st_dev, sb.st_ino);
}
}//Else, Uh oh, can't read information at this level
}
if (!pushed) { break; } //If we didn't obtain any info this pass, no reason to continue
}

if (current_id == root_id) //Unless they're equal, we failed above
{
//Built the path, will always end with a slash
path = "/";
for (std::vector<std::string>::reverse_iterator i = path_components.rbegin(); i != path_components.rend(); ++i)
{
path += *i+"/";
}
success = true;
}
fchdir(start_fd);
}
}
close(start_fd);
}

return(success);
}


Before we accept that as the defacto method to use in your application, let us discuss the flaws.

As mentioned above, it doesn't work on Windows, but a simple #ifdef for Windows can just make it a wrapper around the built in getcwd() with a local buffer of size PATH_MAX, which is fine for Windows, and pretty much no other OS.

This function uses the name getcwd() which can conflict with the built in C based one which is a problem for certain compilers. The fix is to rename it, or put it in its own namespace.

Next, the built in getcwd() implementations I checked only have a trailing slash on the root directory. I personally like having the slash appended, since I'm usually concatenating a filename onto it, but note that if you're not using it for concatenation, but to pass to functions like access(), stat(), opendir(), chdir(), and the like, an OS may not like doing the call with a trailing slash. I've only noticed that being an issue with DJGPP and a few functions. So if it matters to you, the loop near the end of the function can easily be modified to not have the trailing slash, except in the case that the root directory is the entire path.

This function also changes the directory in the process, so it's not thread safe. But then again, many built in implementations aren't thread safe either. If you use threads, calculate all the paths you need prior to creating the threads. Which is probably a good idea, and keep using path names based off of your absolute directories in your program, instead of changing directories during the main execution elsewhere in the program. Otherwise, you'll have to use a mutex around the call, which is also a valid option.

There could also be the issue that some level of the path isn't readable. Which can happen on UNIX, where to enter a directory, one only needs execute permission, and not read permission. I'm not sure what one can do in that case, except maybe fall back on the built in one hoping it does some magical Kernel call to get around it. If anyone has any advice on this one, please post about it in the comments.

Lastly, this function is written in C++, which is annoying for C users. The std::vector can be replaced with a linked list keeping track of the components, and at the end, allocate the buffer size needed, and return the allocated buffer. This requires the user to free the buffer on the outside, but there really isn't any other safe way of doing this.
Alternatively, instead of a linked list, a buffer which is constantly reallocated can be used while building the path, constantly memmove()'ing the built components over to the higher part of the buffer.

During the course of the rest of the program, all path manipulation should be using safe allocation managing strings such as std::string, or should be based off of the above described auto allocating getcwd() and similar functions, and constantly handling the memory management, growing as needed. Be careful when you need to get any path information from elsewhere, as you can never be sure how large it will be.

I hope developers realize that when not on Windows, using the incorrect define PATH_MAX is just wrong, and fix their applications. Next time, we'll discuss how one can implement their own realpath().

2,285 comments:

«Oldest   ‹Older   2201 – 2285 of 2285
Software Training Institute said...

Aimore Technologies is the best Dot Net Training institute in Chennai with 10+ years of experience. We are offering online and classroom training. Visit Us: Dot Net Training in Chennai

Software Training Institute said...

Aimore Technologies is the best Oracle Training institute in Chennai with 10+ years of experience. We are offering online and classroom training. Visit Us: Oracle Training in Chennai

Tech Jankari said...

Thank You for sharing this valuable post.
1. Love Calculator
2. PUBG Lite Apk Download
3. Snack Video apk Download

iteducationcentre said...

great post. Thanks for posting.
CCNA course in Pune

jane robert said...

I would like to express my gratitude for your exceptionally well-written and easy-to-comprehend article on this topic. Clarifying this matter can often be perplexing, but you did an outstanding job. Thank you
Separation Agreement in Virginia

Admin said...

அரசு மற்றும் தனியார் வேலைவாய்ப்பு செய்திகளுக்கு இங்கே கிளிக் செய்யவும்
அன்பு நண்பர்களுக்கு வணக்கம் நீங்கள் வேலை தேடும் ஒரு நபராக இருந்தால் மேற்கண்ட லிங்கை கிளிக் செய்யவும். இந்த தளத்தில் தினமும் அரசு மற்றும் தனியார்துறை வேலைவாய்ப்பு செய்திகள் பதிவு செய்யபடுகின்றன. படித்து பயன் பெறவும் நன்றி!

Sumathu said...

Nice Blog

React JS Training in Chennai
React Js Online Course

MCIT Education said...

Thanks for sharing informative article. This a very good content.Keep sharing with us.
website designing course in rishikesh

SCIENCE CUBE said...

HOW TO STUDY SCINCE CLASSRead or at least scan the textbook material BEFORE you come to class.

Many instructors will go through the chapter in the same order as the book. Knowing about how far the professor will get in one lecture, you can make a good guess as to what they will cover that day. When you read a section for the first time, you might not understand it all. That is not the goal, if it was you could skip class. The point is to get a feel for the material such that when the instructor lectures on it, you have some idea about what they are talking about, and this will make the lectures MUCH more productive for you. Reading the chapter AGAIN after lecture is a good idea as well, emphasizing the same sections your instructor did.

Make sure you have all the appropriate materials needed for class.

Rupesh Kumar said...

Thank you so much for a providing well content, Ziyyara's online spoken English language classes in Kuwait are a fantastic opportunity for individuals looking to improve their English communication skills.
For more info visit Spoken English Language Class in Kuwait

Devotion said...

Thank you for your kinds words being surrounded by people like you make it so much easier to be an achieverExercise To Reduce Hip Fat

Etnica said...

Discover the perfect cocktail dress for your next special event at Etnica Store. Our collection of Puff sleeve dresses will make you look and feel gorgeous. Shop now!

deepotech said...

https://forum.kooora.com/f.aspx?t=38973979

deepotech said...

[url=kooora]https://forum.kooora.com/f.aspx?t=38973979[/url]

ani321india said...


General Knowledge questions




Art and Culture GK


General knowledge questions answers for sarkari job
and competitive exams.

Sanjiv More said...

Your post was excellent, providing valuable information and helpful insights. I eagerly anticipate more updates of this caliber in the future.
more shanaya

EPS Interior Industries said...

interior design

kitchen design


thanks for a information

jamesanderson said...

The engaging content keeps readers hooked, and the potential discovery of a valuable website adds to its appeal. Thank you for sharing this informative piece! The meticulous research and impressive writing style have truly captivated me. Your work is commendable, and the wealth of information provided is fantastic. This insightful and wonderful post deserves my heartfelt appreciation. Thank you for enriching my knowledge
Nueva Jersey Conducción Imprudente

jamesanderson said...
This comment has been removed by the author.
work ANY time, money ANY time said...

very great information, now a days coding is needed every where , i am looking more such informations
thank you

relaxation-station/" rel="no follow">relaxation station

SEO TIPS said...
This comment has been removed by the author.
SEO TIPS said...
This comment has been removed by the author.
SEO TIPS said...

Hey there!

Thank you so much for sharing this insightful content! I found it extremely helpful and informative. It's always great to come across articles that provide valuable information about software training institutes. Speaking of which, I recently came across an amazing software training institute called VYTCDC. They offer a wide range of courses that are perfect for college students like me who are interested in pursuing a career in IT.

I highly recommend checking out their website at Software Training Institute in Chennai. They have a comprehensive list of courses tailored to meet the needs of students and professionals alike. I was particularly impressed by their offerings in web development, data science, and artificial intelligence.

If you're a college student looking to enhance your IT skills, you should definitely explore their Best IT courses for college students. program. It covers all the essential topics and provides hands-on training to ensure you gain practical knowledge and experience.

And if you're looking for a short-term crash course during the summer break, VYT CDC also offers a fantastic Summer Crash for Students. program. It's a great opportunity to make the most of your vacation and learn valuable IT skills.

Once again, thank you for sharing this amazing content, and I hope my recommendations will be helpful to other readers as well. Keep up the excellent work!

Best regards,
flourish

Ambika Kuntal said...

Bullseye Home Builders are Luxury Extension Builders in Melbourne, Australia. They can help you create the perfect extension to your home, tailored to your needs and budget. Contact them today for a consultation.

CyberPunk said...

"Great article! I found the insights you shared ,really informative. As someone interested in [related field], I recently came across some interesting perspectives on a similar subject at https://www.hibuddycool.com. It's a fantastic resource for [specific niche or topic]. Keep up the excellent work!"

Abhishek said...

"It was an incredibly delightful and awe-inspiring post. I genuinely appreciate you sharing it with us."
Visit website:- https://fillerboy.com/
https://fillerboy.com/service.html

Haryanvi Bio said...

Haryanvi Bio

Haryanvi Bio said...

Haryanvi Bio For Instagram For Girls & Boys

Abhishek said...

it was a nice and wonderful blog thanks for sharing with us

https://fillerboy.com/about.html

https://fillerboy.com

EPS Interior Industries said...

Thanks for a valuable information

Kitchen Design

Bedroom Design

Rupesh Kumar said...

Very useful tutorials and very easy to understand. Thanks for sharing. Ziyyara Edutech brings you the perfect solution with our comprehensive online English classes in Riyadh, Saudi Arabia.
For more info visit Spoken English classes in Riyadh or Call +971505593798

EPS Interior Industries said...
This comment has been removed by the author.
EPS Interior Industries said...

Thanks for a Valuable Information

Kitchen Design

Bedroom Design

Livingroom

Wardrobe

EPS Interior Industries said...
This comment has been removed by the author.
EPS Interior Industries said...

thanks for a valuable information

Kitchen design

bedroom design

livingroom

kuldeep said...
This comment has been removed by the author.
Rupesh Kumar said...

I really enjoyed this article. I need more information to learn so kindly update it. Ziyyara Edutech’s online tuition center offers personalized and comprehensive education, specifically designed to cater to the unique needs of Class 7 students.
Book A Free Demo Today visit Home tuition classes for class 7

Prashant Baghel said...

Image Optimization kaise karte hai

Rudraksh Joshi said...

"Your blog has given me such insightful information on the subject that it has deepened my understanding. Thank you for sharing!"
Golang Certification

Rudraksh Joshi said...

"I really enjoyed reading your blog post; it was very well-written and extremely informative."
Golang Course

Rudraksh Joshi said...

I adored your blog post very much! Your observations are so insightful and energizing. It's obvious that you spent a lot of time and effort writing and researching this essay. Your writing is interesting and simple to read, making even difficult subjects seem understandable. Readers like myself who are looking for insightful and well-informed information appreciate you sharing your expertise and viewpoint on this subject. Hopefully you'll write more informative stuff in the future. Continue your excellent job!
Mulesoft Training

Rudraksh Joshi said...

We appreciate your commitment to producing informative and thought-provoking content. I now consider your blog to be a wonderful resource, and I anxiously anticipate your upcoming posts. Continue your excellent work!
Mulesoft Course

Kamakshi_jajoria said...

Positive energy radiates from your post! It struck a deep chord with me. We appreciate you sharing your wise words. Go on shinning! Appreciation UiPath Course

Rudraksh Joshi said...

Great great post; it definitely improved my understanding of the subject.
CCSP Training

Rudraksh Joshi said...

"I wholeheartedly concur with your points; this blog really opened my mind to fresh perspectives!"
CCSP Certification

Rudraksh Joshi said...

This blog definitely opened my eyes to new perspectives, and I couldn't agree more with what you said.
SAP Analytics Cloud Certification

Rudraksh Joshi said...

This blog piece was well-written and really interesting, and it made me hungry to check out more of your stuff.
SAP Analytics Cloud Training

perfectweddinghub said...

Buffet or Sit-Down Dinner

Buffet or Sit-Down Dinner selecting the right wedding reception style. Your wedding day is a cherished moment, and every detail contributes to making it an unforgettable experience. One of the crucial decisions you’ll face during the wedding planning process is choosing between a buffet or a sit-down dinner for your reception. Both options have their merits and can shape the ambiance of your celebration differently. To help you make the right choice, let’s delve into the considerations that can guide your decision.

perfectweddinghub said...

Arab Wedding

The engagement period is an important phase, where families of the bride and groom come together to formalize the union. Rings may be exchanged, and a small gathering is often held to celebrate the engagement. This is a festive event where the bride’s hands and feet are adorned with intricate henna designs.

Rudraksh Joshi said...

"Great post, I found it to be really insightful and stimulating!"
Salesforce CPQ Certification

nutrifyyou said...

Discover NutrifyYou - Your Health & Fitness Haven!


🏋️‍♀️ Get expert tips, tasty recipes, and tailored workouts.
🥗 Simplify nutrition with our meal plans.
📚 Stay informed with our latest insights.
👥 Join our supportive community.
🎁 Exclusive offers await you.

🚀 Start your wellness journey at NutrifyYou.com today!

Instaily Academy said...

Learn Full Stack Development with Python and Django from Instaily Academy.

Free HD Movies Space said...

Led svietidlo
Led lustry
Led Lustre
Lustry
Lustre
led osvetlenie
led svietidla
led panel
led reflektor
led svietidlo
LED Žiarovky
Lustre
LED bodovky
Stropné svietidlá
Vonkajšie osvetlenie
kolajnicove osvetlenie
LED diódové pásiky
Nástenné lampy
Podlahové svietidlá
Bodovky
LED Žiarovky

namechangegazette said...

Founded in 1996, Change of name ads is an Organization helping people to change their names and lead fulfilling lives by choosing the names of their choice

Our business revolves around some of the major cities in India like Mumbai, Delhi, Bangalore, Pune, Hyderabad, Kolkata etc
for more information

Visit name change ads

Shubham Sahare said...

I recently completed the digital marketing course that you recommended, and I wanted to share my thoughts on the experience. In a world where digital marketing is constantly evolving, this course truly stands out as a valuable resource for anyone looking to excel in the field. Digital Marketing

IT TRAINING said...

great content
safety course in chennai

MNK said...

Thanks

BroadMind - IELTS coaching in Madurai and Chennai

Achiramavalli J said...

Best Protein For Woman


Women’s Wellness: Discovering The Best Protein for Woman for Your Journey
Welcome to our comprehensive guide on ‘Best Protein for Woman.’ In this article, we will explore the world of protein, aiming to help you discover the most suitable ‘Best Protein for Woman’ that aligns with your health and wellness goals. Whether you are looking to enhance your muscle health, achieve hormone balance, or simply manage your weight, we’ve got you covered. Join us on this journey to find the ‘Best Protein for Woman’ to unlock your path to optimal well-being.

CV Writing Services said...

Are you ready to take your career to new heights? Our CV writing services in Ireland are your ticket to success. We specialize in crafting eye-catching, keyword-rich CVs that align with Irish job market demands. By incorporating "CV Writing Services Ireland" into your document, you'll maximize your online discoverability and impress potential employers. Invest in your professional future with a CV that commands attention.

Ramanjeet kaur said...

Amritsar Group of Colleges offers an exceptional Fashion design course in Punjab. With a creative curriculum, experienced faculty, and state-of-the-art facilities, it's the perfect place to nurture your passion for fashion and design.

python said...
This comment has been removed by the author.
VISWA Technologies said...

Hey… Setting up an online business in 2023 has never been easier. Take the opportunity now. Don’t waste time. Jump in and try.
SAP EHS Training
SAP C4C Training

VISWA Technologies said...

Of course, what a fantastic website and educational posts, I surely will bookmark your blog. Have an awesome day!
AWS Security Specialty Training
Typescript Training

VISWA Technologies said...

Hi mates, its wonderful article about education and entirely defined, keep it up all the time….
Machine Learning Training
Active Directory Training

VISWA Technologies said...

Very good article. I absolutely appreciate this website. Stick with it!
SCOM 2019 Training
Azure Devops Training
<a href="https://viswaonlinetrainings.com/courses/testing-tools-online-training/>Testing Tools Training</a>

VISWA Technologies said...

This is my first time go to see at here and i am truly happy to read all at single place.
SAP BODS Training
<a href="https://viswaonlinetrainings.com/courses/informatica-data-quality-training/>Informatica Data Quality Training</a>

Coding ninjas coupon code said...

I've perused your blog, and I must say that I appreciate the insightful content. If more individuals adopt these effective strategies, it has the potential to significantly enhance website performance.

Coding ninjas coupon code
Coding ninjas offers
Coding Ninjas discount
Coding Ninjas promo code
Coding Ninjas savings
Coding Ninjas discount code
Coding Ninjas coupon 2024
Coding Ninjas course discount
Coding Ninjas course deal
Coding Ninjas course special offer

Astha said...

Discover Marathi movies in Australia on Maxx TV. Immerse yourself in the vibrant world of Marathi cinema with a diverse selection of films. Maxx TV brings the best of Marathi entertainment to your screens.

Shubhi said...

Unlock SMSF Commercial Property Loans in Melbourne, Australia with Jump Financing —tailored solutions for your investment goals. Empower your SMSF today! Contact us for seamless financial support.

weightlosstipsfoods said...



Mutton Biryani Recipe in Weight loss

"Wholesome mutton biryani: Lean meat, fragrant spices, and brown rice create a low-calorie, flavorful delight for weight-conscious indulgence. #HealthyBiryani"

Robert said...

I am doing my QlikView Server Online Training right now so it is difficult to spare a time nowadays but such post motivates me to come back again.

MHSS SSLC 1988 BATCH MATES said...
This comment has been removed by the author.
crescent careers said...

Hello Everyone,

Supposed if you are looking for abroad jobs, You may try this one.

CRESCENT CAREERS (KILPAUK, CHENNAI)

It will be more Useful for Everyone to find better job in Abroad.

you can refer your friend, neighbor's and anyone for Abroad jobs.

To Get Our Updated Jobs Join

https://jobstoabroad.com/

AROMA OF RAJASTHAN said...

Hello there,

We at Aroma of Rajasthan were truly captivated by your recent blog post. The insights and depth you provided into the topic are commendable and resonate well with our ethos of exploring and appreciating the beauty of destinations.

As a company specializing in crafting unforgettable travel experiences in Rajasthan, we particularly appreciated your emphasis on cultural immersion and local exploration. Your post beautifully aligns with our belief in the transformative power of travel.

We'd love to collaborate or perhaps share some of our unique travel stories and insights from the heart of Rajasthan, which might intrigue your readers. Together, we can inspire more people to embark on journeys that enrich their lives and broaden their horizons.

Keep up the fantastic work on your blog – it’s a treasure trove for travel enthusiasts!
Aroma of Rajasthan (https://aromaofrajasthan.com/)

Karthik Rajalingam said...

Discover various ways to make money online without upfront investment! Leverage your skills and explore diverse online earning opportunities! 💻💸
#OnlineIncome #NoInvestmentNeeded
More Information Here

karthick said...

How to Earn CryptoCoins Instant Payout


Earn Crypto Coins Instant Payout on every day without investment that is good think.Every one can earn easyly for crypto currency for Faucetpay with in Minitue.

karthick said...

How To Earn Crypto

Earn Multiple CryptoCoins it's easyly on every day and every minute.if you need and visits for our website for mor options to earn CryptoCoins.its wonderful opportunity for crypto lovers don't miss it.

ROCK-BOY said...

How
to create an app and make money



🔊 Cʜᴀɴɴᴇʟ
🎯 @HD_MOVIESAPP

Ads Free Channel


🎗J‌O‌I‌N‌  S‌H‌A‌R‌E‌  S‌U‌P‌P‌O‌R‌T‌🎗


Torrent மற்றும் Telegram link இணை HD_MOVIESAPP இல் பெற்றுக்கொள்ளுங்கள்....

UrbanFlex said...

Discover the ultimate fusion of style and performance at UrbanFlex


At UrbanFlex, powered by SPD, we pride ourselves on offering a curated collection of activewear and streetwear that embodies the essence of urban living. Our selection is carefully curated to blend style and functionality seamlessly, providing you with apparel that keeps up with your active lifestyle. From high-performance leggings to stylish hoodies, each piece is designed with the urbanite in mind, ensuring you look and feel your best whether you're hitting the gym or exploring the city streets. With SPD, urban fashion meets versatility, allowing you to navigate your daily adventures with confidence and flair.

www.thespeedsports.com

kosmik said...

kosmik Technologies is the best SQL Training institute in Hyderabad with 12+ years of experience. We are offering online and classroom training. Visit Us:SQL SERVER TRAINING IN HYDERABAD

GCPMASTERS said...

thanks for valuable info
gcp training in hyderabad

Owning A Ship said...

Great post

Become ship owner

BEdigitech said...

Thanks for Sharing. Navigate the digital landscape with confidence using proven digital marketing strategies. From SEO and social media to content marketing and PPC, our expertly crafted strategies ensure maximum impact and ROI. Stay ahead of the curve and reach your audience effectively with our tailored approach. Let us guide you towards digital success with our comprehensive strategies and insights.

Tamil bits news said...

How SEO Works in 2024

we're going through a period at the moment that seeing some of the biggest changes in SEO in well over a decade and in today's video we're going to show you not just how to survive but how to thrive so we're going to cover this in two parts firstly we're going to go through three major changes that are happening.

in SEO right now and then we're going to help you plan for each of these to build them into your strategy so that you can use them to your benefit over the next year change number one Ai and age for sure AI is the buzzword of the day but it is transforming not just the way that marketers do marketing but also how search engines work and present their, results and Google's age or search generative experience is probably the most profound change that we marketers need to be aware of and here's .

Swetha said...

it was a nice and wonderful blog thanks for sharing with us

Java Full Stack Training in Kukatpally

«Oldest ‹Older   2201 – 2285 of 2285   Newer› Newest»