3
0

fdisk.c 156 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880
  1. /* fdisk.c -- Partition table manipulator for Linux.
  2. *
  3. * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
  4. *
  5. * This program is free software. You can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation: either version 1 or
  8. * (at your option) any later version.
  9. *
  10. * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
  11. */
  12. #define UTIL_LINUX_VERSION "2.12"
  13. #define PROC_PARTITIONS "/proc/partitions"
  14. #include <features.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h> /* stat */
  17. #include <ctype.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <unistd.h>
  23. #include <fcntl.h>
  24. #include <setjmp.h>
  25. #include <assert.h> /* assert */
  26. #include <getopt.h>
  27. #include <endian.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/param.h>
  30. #include <sys/sysmacros.h> /* major */
  31. #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
  32. /* Copied from linux/major.h */
  33. #define FLOPPY_MAJOR 2
  34. #include <sys/utsname.h>
  35. #include "busybox.h"
  36. #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
  37. #define DKTYPENAMES
  38. #define _(Text) Text
  39. #define BLKRRPART _IO(0x12,95) /* re-read partition table */
  40. #define BLKGETSIZE _IO(0x12,96) /* return device size */
  41. #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
  42. #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
  43. /* Avoid conflicts with the 2.6 kernel headers, which define
  44. * _IOR rather differently */
  45. #undef _IOR
  46. #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
  47. #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
  48. /*
  49. fdisk.h
  50. */
  51. #define DEFAULT_SECTOR_SIZE 512
  52. #define MAX_SECTOR_SIZE 2048
  53. #define SECTOR_SIZE 512 /* still used in BSD code */
  54. #define MAXIMUM_PARTS 60
  55. #define ACTIVE_FLAG 0x80
  56. #define EXTENDED 0x05
  57. #define WIN98_EXTENDED 0x0f
  58. #define LINUX_PARTITION 0x81
  59. #define LINUX_SWAP 0x82
  60. #define LINUX_NATIVE 0x83
  61. #define LINUX_EXTENDED 0x85
  62. #define LINUX_LVM 0x8e
  63. #define LINUX_RAID 0xfd
  64. #define SUNOS_SWAP 3
  65. #define WHOLE_DISK 5
  66. #define IS_EXTENDED(i) \
  67. ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
  68. #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
  69. #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
  70. #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
  71. #ifdef CONFIG_FEATURE_SUN_LABEL
  72. #define SCSI_IOCTL_GET_IDLUN 0x5382
  73. #endif
  74. /* including <linux/hdreg.h> also fails */
  75. struct hd_geometry {
  76. unsigned char heads;
  77. unsigned char sectors;
  78. unsigned short cylinders;
  79. unsigned long start;
  80. };
  81. #define HDIO_GETGEO 0x0301 /* get device geometry */
  82. struct systypes {
  83. const unsigned char *name;
  84. };
  85. static uint sector_size = DEFAULT_SECTOR_SIZE,
  86. user_set_sector_size,
  87. sector_offset = 1;
  88. /*
  89. * Raw disk label. For DOS-type partition tables the MBR,
  90. * with descriptions of the primary partitions.
  91. */
  92. static char MBRbuffer[MAX_SECTOR_SIZE];
  93. #ifdef CONFIG_FEATURE_SUN_LABEL
  94. static int sun_label; /* looking at sun disklabel */
  95. #else
  96. #define sun_label 0
  97. #endif
  98. #ifdef CONFIG_FEATURE_SGI_LABEL
  99. static int sgi_label; /* looking at sgi disklabel */
  100. #else
  101. #define sgi_label 0
  102. #endif
  103. #ifdef CONFIG_FEATURE_AIX_LABEL
  104. static int aix_label; /* looking at aix disklabel */
  105. #else
  106. #define aix_label 0
  107. #endif
  108. #ifdef CONFIG_FEATURE_OSF_LABEL
  109. static int osf_label; /* looking at OSF/1 disklabel */
  110. static int possibly_osf_label;
  111. #else
  112. #define osf_label 0
  113. #endif
  114. #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
  115. static uint heads, sectors, cylinders;
  116. static void update_units(void);
  117. /*
  118. * return partition name - uses static storage unless buf is supplied
  119. */
  120. static const char *
  121. partname(const char *dev, int pno, int lth) {
  122. static char buffer[80];
  123. const char *p;
  124. int w, wp;
  125. int bufsiz;
  126. char *bufp;
  127. bufp = buffer;
  128. bufsiz = sizeof(buffer);
  129. w = strlen(dev);
  130. p = "";
  131. if (isdigit(dev[w-1]))
  132. p = "p";
  133. /* devfs kludge - note: fdisk partition names are not supposed
  134. to equal kernel names, so there is no reason to do this */
  135. if (strcmp (dev + w - 4, "disc") == 0) {
  136. w -= 4;
  137. p = "part";
  138. }
  139. wp = strlen(p);
  140. if (lth) {
  141. snprintf(bufp, bufsiz, "%*.*s%s%-2u",
  142. lth-wp-2, w, dev, p, pno);
  143. } else {
  144. snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
  145. }
  146. return bufp;
  147. }
  148. struct partition {
  149. unsigned char boot_ind; /* 0x80 - active */
  150. unsigned char head; /* starting head */
  151. unsigned char sector; /* starting sector */
  152. unsigned char cyl; /* starting cylinder */
  153. unsigned char sys_ind; /* What partition type */
  154. unsigned char end_head; /* end head */
  155. unsigned char end_sector; /* end sector */
  156. unsigned char end_cyl; /* end cylinder */
  157. unsigned char start4[4]; /* starting sector counting from 0 */
  158. unsigned char size4[4]; /* nr of sectors in partition */
  159. } __attribute__((__packed__));
  160. enum failure {
  161. ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
  162. unable_to_write
  163. };
  164. enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
  165. static const char *disk_device;
  166. static int fd; /* the disk */
  167. static int partitions = 4; /* maximum partition + 1 */
  168. static uint display_in_cyl_units = 1;
  169. static uint units_per_sector = 1;
  170. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  171. static char *line_ptr;
  172. static void change_units(void);
  173. static void reread_partition_table(int leave);
  174. static void delete_partition(int i);
  175. static int get_partition(int warn, int max);
  176. static void list_types(const struct systypes *sys);
  177. static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
  178. #endif
  179. static const char *partition_type(unsigned char type);
  180. static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
  181. static void get_geometry(void);
  182. static int get_boot(enum action what);
  183. #define PLURAL 0
  184. #define SINGULAR 1
  185. #define hex_val(c) ({ \
  186. char _c = (c); \
  187. isdigit(_c) ? _c - '0' : \
  188. tolower(_c) + 10 - 'a'; \
  189. })
  190. #define LINE_LENGTH 800
  191. #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
  192. (n) * sizeof(struct partition)))
  193. #define sector(s) ((s) & 0x3f)
  194. #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
  195. #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
  196. ((h) + heads * cylinder(s,c)))
  197. #define set_hsc(h,s,c,sector) { \
  198. s = sector % sectors + 1; \
  199. sector /= sectors; \
  200. h = sector % heads; \
  201. sector /= heads; \
  202. c = sector & 0xff; \
  203. s |= (sector >> 2) & 0xc0; \
  204. }
  205. static int32_t get_start_sect(const struct partition *p);
  206. static int32_t get_nr_sects(const struct partition *p);
  207. /*
  208. * per partition table entry data
  209. *
  210. * The four primary partitions have the same sectorbuffer (MBRbuffer)
  211. * and have NULL ext_pointer.
  212. * Each logical partition table entry has two pointers, one for the
  213. * partition and one link to the next one.
  214. */
  215. static struct pte {
  216. struct partition *part_table; /* points into sectorbuffer */
  217. struct partition *ext_pointer; /* points into sectorbuffer */
  218. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  219. char changed; /* boolean */
  220. #endif
  221. off_t offset; /* disk sector number */
  222. char *sectorbuffer; /* disk sector contents */
  223. } ptes[MAXIMUM_PARTS];
  224. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  225. static void
  226. set_all_unchanged(void) {
  227. int i;
  228. for (i = 0; i < MAXIMUM_PARTS; i++)
  229. ptes[i].changed = 0;
  230. }
  231. static void
  232. set_changed(int i) {
  233. ptes[i].changed = 1;
  234. }
  235. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  236. #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
  237. static struct partition *
  238. get_part_table(int i) {
  239. return ptes[i].part_table;
  240. }
  241. #endif
  242. static const char *
  243. str_units(int n) { /* n==1: use singular */
  244. if (n == 1)
  245. return display_in_cyl_units ? _("cylinder") : _("sector");
  246. else
  247. return display_in_cyl_units ? _("cylinders") : _("sectors");
  248. }
  249. static int
  250. valid_part_table_flag(const unsigned char *b) {
  251. return (b[510] == 0x55 && b[511] == 0xaa);
  252. }
  253. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  254. static char line_buffer[LINE_LENGTH];
  255. /* read line; return 0 or first char */
  256. static int
  257. read_line(void)
  258. {
  259. static int got_eof = 0;
  260. fflush (stdout); /* requested by niles@scyld.com */
  261. line_ptr = line_buffer;
  262. if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
  263. if (feof(stdin))
  264. got_eof++; /* user typed ^D ? */
  265. if (got_eof >= 3) {
  266. fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
  267. exit(1);
  268. }
  269. return 0;
  270. }
  271. while (*line_ptr && !isgraph(*line_ptr))
  272. line_ptr++;
  273. return *line_ptr;
  274. }
  275. static char
  276. read_char(const char *mesg)
  277. {
  278. do {
  279. fputs(mesg, stdout);
  280. } while (!read_line());
  281. return *line_ptr;
  282. }
  283. static char
  284. read_chars(const char *mesg)
  285. {
  286. fputs(mesg, stdout);
  287. if (!read_line()) {
  288. *line_ptr = '\n';
  289. line_ptr[1] = 0;
  290. }
  291. return *line_ptr;
  292. }
  293. static int
  294. read_hex(const struct systypes *sys)
  295. {
  296. int hex;
  297. while (1)
  298. {
  299. read_char(_("Hex code (type L to list codes): "));
  300. if (*line_ptr == 'l' || *line_ptr == 'L')
  301. list_types(sys);
  302. else if (isxdigit (*line_ptr))
  303. {
  304. hex = 0;
  305. do
  306. hex = hex << 4 | hex_val(*line_ptr++);
  307. while (isxdigit(*line_ptr));
  308. return hex;
  309. }
  310. }
  311. }
  312. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  313. #ifdef CONFIG_FEATURE_AIX_LABEL
  314. /*
  315. * Copyright (C) Andreas Neuper, Sep 1998.
  316. * This file may be redistributed under
  317. * the terms of the GNU Public License.
  318. */
  319. typedef struct {
  320. unsigned int magic; /* expect AIX_LABEL_MAGIC */
  321. unsigned int fillbytes1[124];
  322. unsigned int physical_volume_id;
  323. unsigned int fillbytes2[124];
  324. } aix_partition;
  325. #define AIX_LABEL_MAGIC 0xc9c2d4c1
  326. #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
  327. #define AIX_INFO_MAGIC 0x00072959
  328. #define AIX_INFO_MAGIC_SWAPPED 0x59290700
  329. #define aixlabel ((aix_partition *)MBRbuffer)
  330. /*
  331. Changes:
  332. * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  333. * Internationalization
  334. *
  335. * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
  336. * Some fixes
  337. */
  338. static int aix_other_endian;
  339. static short aix_volumes=1;
  340. /*
  341. * only dealing with free blocks here
  342. */
  343. static void
  344. aix_info( void ) {
  345. puts(
  346. _("\n\tThere is a valid AIX label on this disk.\n"
  347. "\tUnfortunately Linux cannot handle these\n"
  348. "\tdisks at the moment. Nevertheless some\n"
  349. "\tadvice:\n"
  350. "\t1. fdisk will destroy its contents on write.\n"
  351. "\t2. Be sure that this disk is NOT a still vital\n"
  352. "\t part of a volume group. (Otherwise you may\n"
  353. "\t erase the other disks as well, if unmirrored.)\n"
  354. "\t3. Before deleting this physical volume be sure\n"
  355. "\t to remove the disk logically from your AIX\n"
  356. "\t machine. (Otherwise you become an AIXpert).")
  357. );
  358. }
  359. static void
  360. aix_nolabel( void )
  361. {
  362. aixlabel->magic = 0;
  363. aix_label = 0;
  364. partitions = 4;
  365. memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
  366. return;
  367. }
  368. static int
  369. check_aix_label( void )
  370. {
  371. if (aixlabel->magic != AIX_LABEL_MAGIC &&
  372. aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
  373. aix_label = 0;
  374. aix_other_endian = 0;
  375. return 0;
  376. }
  377. aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
  378. update_units();
  379. aix_label = 1;
  380. partitions= 1016;
  381. aix_volumes = 15;
  382. aix_info();
  383. aix_nolabel(); /* %% */
  384. aix_label = 1; /* %% */
  385. return 1;
  386. }
  387. #endif /* AIX_LABEL */
  388. #ifdef CONFIG_FEATURE_OSF_LABEL
  389. /*
  390. * Copyright (c) 1987, 1988 Regents of the University of California.
  391. * All rights reserved.
  392. *
  393. * Redistribution and use in source and binary forms, with or without
  394. * modification, are permitted provided that the following conditions
  395. * are met:
  396. * 1. Redistributions of source code must retain the above copyright
  397. * notice, this list of conditions and the following disclaimer.
  398. * 2. Redistributions in binary form must reproduce the above copyright
  399. * notice, this list of conditions and the following disclaimer in the
  400. * documentation and/or other materials provided with the distribution.
  401. * 3. All advertising materials mentioning features or use of this software
  402. * must display the following acknowledgment:
  403. * This product includes software developed by the University of
  404. * California, Berkeley and its contributors.
  405. * 4. Neither the name of the University nor the names of its contributors
  406. * may be used to endorse or promote products derived from this software
  407. * without specific prior written permission.
  408. *
  409. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  410. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  411. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  412. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  413. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  414. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  415. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  416. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  417. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  418. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  419. * SUCH DAMAGE.
  420. */
  421. #ifndef BSD_DISKMAGIC
  422. #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
  423. #endif
  424. #ifndef BSD_MAXPARTITIONS
  425. #define BSD_MAXPARTITIONS 16
  426. #endif
  427. #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
  428. #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
  429. #define BSD_LABELSECTOR 1
  430. #define BSD_LABELOFFSET 0
  431. #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
  432. #define BSD_LABELSECTOR 0
  433. #define BSD_LABELOFFSET 64
  434. #elif defined (__s390__) || defined (__s390x__)
  435. #define BSD_LABELSECTOR 1
  436. #define BSD_LABELOFFSET 0
  437. #else
  438. #error unknown architecture
  439. #endif
  440. #define BSD_BBSIZE 8192 /* size of boot area, with label */
  441. #define BSD_SBSIZE 8192 /* max size of fs superblock */
  442. struct xbsd_disklabel {
  443. uint32_t d_magic; /* the magic number */
  444. int16_t d_type; /* drive type */
  445. int16_t d_subtype; /* controller/d_type specific */
  446. char d_typename[16]; /* type name, e.g. "eagle" */
  447. char d_packname[16]; /* pack identifier */
  448. /* disk geometry: */
  449. uint32_t d_secsize; /* # of bytes per sector */
  450. uint32_t d_nsectors; /* # of data sectors per track */
  451. uint32_t d_ntracks; /* # of tracks per cylinder */
  452. uint32_t d_ncylinders; /* # of data cylinders per unit */
  453. uint32_t d_secpercyl; /* # of data sectors per cylinder */
  454. uint32_t d_secperunit; /* # of data sectors per unit */
  455. /*
  456. * Spares (bad sector replacements) below
  457. * are not counted in d_nsectors or d_secpercyl.
  458. * Spare sectors are assumed to be physical sectors
  459. * which occupy space at the end of each track and/or cylinder.
  460. */
  461. uint16_t d_sparespertrack; /* # of spare sectors per track */
  462. uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
  463. /*
  464. * Alternate cylinders include maintenance, replacement,
  465. * configuration description areas, etc.
  466. */
  467. uint32_t d_acylinders; /* # of alt. cylinders per unit */
  468. /* hardware characteristics: */
  469. /*
  470. * d_interleave, d_trackskew and d_cylskew describe perturbations
  471. * in the media format used to compensate for a slow controller.
  472. * Interleave is physical sector interleave, set up by the formatter
  473. * or controller when formatting. When interleaving is in use,
  474. * logically adjacent sectors are not physically contiguous,
  475. * but instead are separated by some number of sectors.
  476. * It is specified as the ratio of physical sectors traversed
  477. * per logical sector. Thus an interleave of 1:1 implies contiguous
  478. * layout, while 2:1 implies that logical sector 0 is separated
  479. * by one sector from logical sector 1.
  480. * d_trackskew is the offset of sector 0 on track N
  481. * relative to sector 0 on track N-1 on the same cylinder.
  482. * Finally, d_cylskew is the offset of sector 0 on cylinder N
  483. * relative to sector 0 on cylinder N-1.
  484. */
  485. uint16_t d_rpm; /* rotational speed */
  486. uint16_t d_interleave; /* hardware sector interleave */
  487. uint16_t d_trackskew; /* sector 0 skew, per track */
  488. uint16_t d_cylskew; /* sector 0 skew, per cylinder */
  489. uint32_t d_headswitch; /* head switch time, usec */
  490. uint32_t d_trkseek; /* track-to-track seek, usec */
  491. uint32_t d_flags; /* generic flags */
  492. #define NDDATA 5
  493. uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
  494. #define NSPARE 5
  495. uint32_t d_spare[NSPARE]; /* reserved for future use */
  496. uint32_t d_magic2; /* the magic number (again) */
  497. uint16_t d_checksum; /* xor of data incl. partitions */
  498. /* filesystem and partition information: */
  499. uint16_t d_npartitions; /* number of partitions in following */
  500. uint32_t d_bbsize; /* size of boot area at sn0, bytes */
  501. uint32_t d_sbsize; /* max size of fs superblock, bytes */
  502. struct xbsd_partition { /* the partition table */
  503. uint32_t p_size; /* number of sectors in partition */
  504. uint32_t p_offset; /* starting sector */
  505. uint32_t p_fsize; /* filesystem basic fragment size */
  506. uint8_t p_fstype; /* filesystem type, see below */
  507. uint8_t p_frag; /* filesystem fragments per block */
  508. uint16_t p_cpg; /* filesystem cylinders per group */
  509. } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
  510. };
  511. /* d_type values: */
  512. #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
  513. #define BSD_DTYPE_MSCP 2 /* MSCP */
  514. #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
  515. #define BSD_DTYPE_SCSI 4 /* SCSI */
  516. #define BSD_DTYPE_ESDI 5 /* ESDI interface */
  517. #define BSD_DTYPE_ST506 6 /* ST506 etc. */
  518. #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
  519. #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
  520. #define BSD_DTYPE_FLOPPY 10 /* floppy */
  521. /* d_subtype values: */
  522. #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
  523. #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
  524. #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
  525. #ifdef DKTYPENAMES
  526. static const char * const xbsd_dktypenames[] = {
  527. "unknown",
  528. "SMD",
  529. "MSCP",
  530. "old DEC",
  531. "SCSI",
  532. "ESDI",
  533. "ST506",
  534. "HP-IB",
  535. "HP-FL",
  536. "type 9",
  537. "floppy",
  538. 0
  539. };
  540. #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
  541. #endif
  542. /*
  543. * Filesystem type and version.
  544. * Used to interpret other filesystem-specific
  545. * per-partition information.
  546. */
  547. #define BSD_FS_UNUSED 0 /* unused */
  548. #define BSD_FS_SWAP 1 /* swap */
  549. #define BSD_FS_V6 2 /* Sixth Edition */
  550. #define BSD_FS_V7 3 /* Seventh Edition */
  551. #define BSD_FS_SYSV 4 /* System V */
  552. #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
  553. #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
  554. #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
  555. #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
  556. #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
  557. #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
  558. #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
  559. #define BSD_FS_ISOFS BSD_FS_ISO9660
  560. #define BSD_FS_BOOT 13 /* partition contains bootstrap */
  561. #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
  562. #define BSD_FS_HFS 15 /* Macintosh HFS */
  563. #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
  564. /* this is annoying, but it's also the way it is :-( */
  565. #ifdef __alpha__
  566. #define BSD_FS_EXT2 8 /* ext2 file system */
  567. #else
  568. #define BSD_FS_MSDOS 8 /* MS-DOS file system */
  569. #endif
  570. #ifdef DKTYPENAMES
  571. static const struct systypes xbsd_fstypes[] = {
  572. /* BSD_FS_UNUSED */ {"\x00" "unused"},
  573. /* BSD_FS_SWAP */ {"\x01" "swap"},
  574. /* BSD_FS_V6 */ {"\x02" "Version 6"},
  575. /* BSD_FS_V7 */ {"\x03" "Version 7"},
  576. /* BSD_FS_SYSV */ {"\x04" "System V"},
  577. /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
  578. /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
  579. /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
  580. #ifdef __alpha__
  581. /* BSD_FS_EXT2 */ {"\x08" "ext2"},
  582. #else
  583. /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
  584. #endif
  585. /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
  586. /* BSD_FS_OTHER */ {"\x0a" "unknown"},
  587. /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
  588. /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
  589. /* BSD_FS_BOOT */ {"\x0d" "boot"},
  590. /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
  591. /* BSD_FS_HFS */ {"\x0f" "HFS"},
  592. /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
  593. { NULL }
  594. };
  595. #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
  596. #endif
  597. /*
  598. * flags shared by various drives:
  599. */
  600. #define BSD_D_REMOVABLE 0x01 /* removable media */
  601. #define BSD_D_ECC 0x02 /* supports ECC */
  602. #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
  603. #define BSD_D_RAMDISK 0x08 /* disk emulator */
  604. #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
  605. #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
  606. #endif /* OSF_LABEL */
  607. /*
  608. * Copyright (C) Andreas Neuper, Sep 1998.
  609. * This file may be modified and redistributed under
  610. * the terms of the GNU Public License.
  611. */
  612. struct device_parameter { /* 48 bytes */
  613. unsigned char skew;
  614. unsigned char gap1;
  615. unsigned char gap2;
  616. unsigned char sparecyl;
  617. unsigned short pcylcount;
  618. unsigned short head_vol0;
  619. unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
  620. unsigned char cmd_tag_queue_depth;
  621. unsigned char unused0;
  622. unsigned short unused1;
  623. unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
  624. unsigned short bytes;
  625. unsigned short ilfact;
  626. unsigned int flags; /* controller flags */
  627. unsigned int datarate;
  628. unsigned int retries_on_error;
  629. unsigned int ms_per_word;
  630. unsigned short xylogics_gap1;
  631. unsigned short xylogics_syncdelay;
  632. unsigned short xylogics_readdelay;
  633. unsigned short xylogics_gap2;
  634. unsigned short xylogics_readgate;
  635. unsigned short xylogics_writecont;
  636. };
  637. #define SGI_VOLHDR 0x00
  638. /* 1 and 2 were used for drive types no longer supported by SGI */
  639. #define SGI_SWAP 0x03
  640. /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
  641. #define SGI_VOLUME 0x06
  642. #define SGI_EFS 0x07
  643. #define SGI_LVOL 0x08
  644. #define SGI_RLVOL 0x09
  645. #define SGI_XFS 0x0a
  646. #define SGI_XFSLOG 0x0b
  647. #define SGI_XLV 0x0c
  648. #define SGI_XVM 0x0d
  649. #define ENTIRE_DISK SGI_VOLUME
  650. /*
  651. * controller flags
  652. */
  653. #define SECTOR_SLIP 0x01
  654. #define SECTOR_FWD 0x02
  655. #define TRACK_FWD 0x04
  656. #define TRACK_MULTIVOL 0x08
  657. #define IGNORE_ERRORS 0x10
  658. #define RESEEK 0x20
  659. #define ENABLE_CMDTAGQ 0x40
  660. typedef struct {
  661. unsigned int magic; /* expect SGI_LABEL_MAGIC */
  662. unsigned short boot_part; /* active boot partition */
  663. unsigned short swap_part; /* active swap partition */
  664. unsigned char boot_file[16]; /* name of the bootfile */
  665. struct device_parameter devparam; /* 1 * 48 bytes */
  666. struct volume_directory { /* 15 * 16 bytes */
  667. unsigned char vol_file_name[8]; /* a character array */
  668. unsigned int vol_file_start; /* number of logical block */
  669. unsigned int vol_file_size; /* number of bytes */
  670. } directory[15];
  671. struct sgi_partition { /* 16 * 12 bytes */
  672. unsigned int num_sectors; /* number of blocks */
  673. unsigned int start_sector; /* must be cylinder aligned */
  674. unsigned int id;
  675. } partitions[16];
  676. unsigned int csum;
  677. unsigned int fillbytes;
  678. } sgi_partition;
  679. typedef struct {
  680. unsigned int magic; /* looks like a magic number */
  681. unsigned int a2;
  682. unsigned int a3;
  683. unsigned int a4;
  684. unsigned int b1;
  685. unsigned short b2;
  686. unsigned short b3;
  687. unsigned int c[16];
  688. unsigned short d[3];
  689. unsigned char scsi_string[50];
  690. unsigned char serial[137];
  691. unsigned short check1816;
  692. unsigned char installer[225];
  693. } sgiinfo;
  694. #define SGI_LABEL_MAGIC 0x0be5a941
  695. #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
  696. #define SGI_INFO_MAGIC 0x00072959
  697. #define SGI_INFO_MAGIC_SWAPPED 0x59290700
  698. #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
  699. : (uint16_t)(x))
  700. #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
  701. : (uint32_t)(x))
  702. #define sgilabel ((sgi_partition *)MBRbuffer)
  703. #define sgiparam (sgilabel->devparam)
  704. typedef struct {
  705. unsigned char info[128]; /* Informative text string */
  706. unsigned char spare0[14];
  707. struct sun_info {
  708. unsigned char spare1;
  709. unsigned char id;
  710. unsigned char spare2;
  711. unsigned char flags;
  712. } infos[8];
  713. unsigned char spare1[246]; /* Boot information etc. */
  714. unsigned short rspeed; /* Disk rotational speed */
  715. unsigned short pcylcount; /* Physical cylinder count */
  716. unsigned short sparecyl; /* extra sects per cylinder */
  717. unsigned char spare2[4]; /* More magic... */
  718. unsigned short ilfact; /* Interleave factor */
  719. unsigned short ncyl; /* Data cylinder count */
  720. unsigned short nacyl; /* Alt. cylinder count */
  721. unsigned short ntrks; /* Tracks per cylinder */
  722. unsigned short nsect; /* Sectors per track */
  723. unsigned char spare3[4]; /* Even more magic... */
  724. struct sun_partition {
  725. uint32_t start_cylinder;
  726. uint32_t num_sectors;
  727. } partitions[8];
  728. unsigned short magic; /* Magic number */
  729. unsigned short csum; /* Label xor'd checksum */
  730. } sun_partition;
  731. #define SUN_LABEL_MAGIC 0xDABE
  732. #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
  733. #define sunlabel ((sun_partition *)MBRbuffer)
  734. #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
  735. : (uint16_t)(x))
  736. #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
  737. : (uint32_t)(x))
  738. #ifdef CONFIG_FEATURE_OSF_LABEL
  739. /*
  740. Changes:
  741. 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
  742. 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
  743. support for OSF/1 disklabels on Alpha.
  744. Also fixed unaligned accesses in alpha_bootblock_checksum()
  745. */
  746. #define FREEBSD_PARTITION 0xa5
  747. #define NETBSD_PARTITION 0xa9
  748. static void xbsd_delete_part (void);
  749. static void xbsd_new_part (void);
  750. static void xbsd_write_disklabel (void);
  751. static int xbsd_create_disklabel (void);
  752. static void xbsd_edit_disklabel (void);
  753. static void xbsd_write_bootstrap (void);
  754. static void xbsd_change_fstype (void);
  755. static int xbsd_get_part_index (int max);
  756. static int xbsd_check_new_partition (int *i);
  757. static void xbsd_list_types (void);
  758. static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
  759. static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
  760. int pindex);
  761. static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
  762. static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
  763. #if defined (__alpha__)
  764. static void alpha_bootblock_checksum (char *boot);
  765. #endif
  766. #if !defined (__alpha__)
  767. static int xbsd_translate_fstype (int linux_type);
  768. static void xbsd_link_part (void);
  769. static struct partition *xbsd_part;
  770. static int xbsd_part_index;
  771. #endif
  772. #if defined (__alpha__)
  773. /* We access this through a uint64_t * when checksumming */
  774. static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
  775. #else
  776. static char disklabelbuffer[BSD_BBSIZE];
  777. #endif
  778. static struct xbsd_disklabel xbsd_dlabel;
  779. #define bsd_cround(n) \
  780. (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
  781. /*
  782. * Test whether the whole disk has BSD disk label magic.
  783. *
  784. * Note: often reformatting with DOS-type label leaves the BSD magic,
  785. * so this does not mean that there is a BSD disk label.
  786. */
  787. static int
  788. check_osf_label(void) {
  789. if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
  790. return 0;
  791. return 1;
  792. }
  793. static void xbsd_print_disklabel(int);
  794. static int
  795. btrydev (const char * dev) {
  796. if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
  797. return -1;
  798. printf(_("\nBSD label for device: %s\n"), dev);
  799. xbsd_print_disklabel (0);
  800. return 0;
  801. }
  802. static void
  803. bmenu (void) {
  804. puts (_("Command action"));
  805. puts (_("\td\tdelete a BSD partition"));
  806. puts (_("\te\tedit drive data"));
  807. puts (_("\ti\tinstall bootstrap"));
  808. puts (_("\tl\tlist known filesystem types"));
  809. puts (_("\tm\tprint this menu"));
  810. puts (_("\tn\tadd a new BSD partition"));
  811. puts (_("\tp\tprint BSD partition table"));
  812. puts (_("\tq\tquit without saving changes"));
  813. puts (_("\tr\treturn to main menu"));
  814. puts (_("\ts\tshow complete disklabel"));
  815. puts (_("\tt\tchange a partition's filesystem id"));
  816. puts (_("\tu\tchange units (cylinders/sectors)"));
  817. puts (_("\tw\twrite disklabel to disk"));
  818. #if !defined (__alpha__)
  819. puts (_("\tx\tlink BSD partition to non-BSD partition"));
  820. #endif
  821. }
  822. #if !defined (__alpha__)
  823. static int
  824. hidden(int type) {
  825. return type ^ 0x10;
  826. }
  827. static int
  828. is_bsd_partition_type(int type) {
  829. return (type == FREEBSD_PARTITION ||
  830. type == hidden(FREEBSD_PARTITION) ||
  831. type == NETBSD_PARTITION ||
  832. type == hidden(NETBSD_PARTITION));
  833. }
  834. #endif
  835. static void
  836. bselect (void) {
  837. #if !defined (__alpha__)
  838. int t, ss;
  839. struct partition *p;
  840. for (t=0; t<4; t++) {
  841. p = get_part_table(t);
  842. if (p && is_bsd_partition_type(p->sys_ind)) {
  843. xbsd_part = p;
  844. xbsd_part_index = t;
  845. ss = get_start_sect(xbsd_part);
  846. if (ss == 0) {
  847. fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
  848. partname(disk_device, t+1, 0));
  849. return;
  850. }
  851. printf (_("Reading disklabel of %s at sector %d.\n"),
  852. partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
  853. if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
  854. if (xbsd_create_disklabel () == 0)
  855. return;
  856. break;
  857. }
  858. }
  859. if (t == 4) {
  860. printf (_("There is no *BSD partition on %s.\n"), disk_device);
  861. return;
  862. }
  863. #elif defined (__alpha__)
  864. if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
  865. if (xbsd_create_disklabel () == 0)
  866. exit ( EXIT_SUCCESS );
  867. #endif
  868. while (1) {
  869. putchar ('\n');
  870. switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
  871. case 'd':
  872. xbsd_delete_part ();
  873. break;
  874. case 'e':
  875. xbsd_edit_disklabel ();
  876. break;
  877. case 'i':
  878. xbsd_write_bootstrap ();
  879. break;
  880. case 'l':
  881. xbsd_list_types ();
  882. break;
  883. case 'n':
  884. xbsd_new_part ();
  885. break;
  886. case 'p':
  887. xbsd_print_disklabel (0);
  888. break;
  889. case 'q':
  890. close (fd);
  891. exit ( EXIT_SUCCESS );
  892. case 'r':
  893. return;
  894. case 's':
  895. xbsd_print_disklabel (1);
  896. break;
  897. case 't':
  898. xbsd_change_fstype ();
  899. break;
  900. case 'u':
  901. change_units();
  902. break;
  903. case 'w':
  904. xbsd_write_disklabel ();
  905. break;
  906. #if !defined (__alpha__)
  907. case 'x':
  908. xbsd_link_part ();
  909. break;
  910. #endif
  911. default:
  912. bmenu ();
  913. break;
  914. }
  915. }
  916. }
  917. static void
  918. xbsd_delete_part (void)
  919. {
  920. int i;
  921. i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
  922. xbsd_dlabel.d_partitions[i].p_size = 0;
  923. xbsd_dlabel.d_partitions[i].p_offset = 0;
  924. xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
  925. if (xbsd_dlabel.d_npartitions == i + 1)
  926. while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
  927. xbsd_dlabel.d_npartitions--;
  928. }
  929. static void
  930. xbsd_new_part (void)
  931. {
  932. off_t begin, end;
  933. char mesg[256];
  934. int i;
  935. if (!xbsd_check_new_partition (&i))
  936. return;
  937. #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
  938. begin = get_start_sect(xbsd_part);
  939. end = begin + get_nr_sects(xbsd_part) - 1;
  940. #else
  941. begin = 0;
  942. end = xbsd_dlabel.d_secperunit - 1;
  943. #endif
  944. snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
  945. begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
  946. 0, mesg);
  947. if (display_in_cyl_units)
  948. begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
  949. snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
  950. str_units(SINGULAR));
  951. end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
  952. bsd_cround (begin), mesg);
  953. if (display_in_cyl_units)
  954. end = end * xbsd_dlabel.d_secpercyl - 1;
  955. xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
  956. xbsd_dlabel.d_partitions[i].p_offset = begin;
  957. xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
  958. }
  959. static void
  960. xbsd_print_disklabel (int show_all) {
  961. struct xbsd_disklabel *lp = &xbsd_dlabel;
  962. struct xbsd_partition *pp;
  963. int i, j;
  964. if (show_all) {
  965. #if defined (__alpha__)
  966. printf("# %s:\n", disk_device);
  967. #else
  968. printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
  969. #endif
  970. if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
  971. printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
  972. else
  973. printf(_("type: %d\n"), lp->d_type);
  974. printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
  975. printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
  976. printf(_("flags:"));
  977. if (lp->d_flags & BSD_D_REMOVABLE)
  978. printf(_(" removable"));
  979. if (lp->d_flags & BSD_D_ECC)
  980. printf(_(" ecc"));
  981. if (lp->d_flags & BSD_D_BADSECT)
  982. printf(_(" badsect"));
  983. printf("\n");
  984. /* On various machines the fields of *lp are short/int/long */
  985. /* In order to avoid problems, we cast them all to long. */
  986. printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
  987. printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
  988. printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
  989. printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
  990. printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
  991. printf(_("rpm: %d\n"), lp->d_rpm);
  992. printf(_("interleave: %d\n"), lp->d_interleave);
  993. printf(_("trackskew: %d\n"), lp->d_trackskew);
  994. printf(_("cylinderskew: %d\n"), lp->d_cylskew);
  995. printf(_("headswitch: %ld\t\t# milliseconds\n"),
  996. (long) lp->d_headswitch);
  997. printf(_("track-to-track seek: %ld\t# milliseconds\n"),
  998. (long) lp->d_trkseek);
  999. printf(_("drivedata: "));
  1000. for (i = NDDATA - 1; i >= 0; i--)
  1001. if (lp->d_drivedata[i])
  1002. break;
  1003. if (i < 0)
  1004. i = 0;
  1005. for (j = 0; j <= i; j++)
  1006. printf("%ld ", (long) lp->d_drivedata[j]);
  1007. }
  1008. printf(_("\n%d partitions:\n"), lp->d_npartitions);
  1009. printf(_("# start end size fstype [fsize bsize cpg]\n"));
  1010. pp = lp->d_partitions;
  1011. for (i = 0; i < lp->d_npartitions; i++, pp++) {
  1012. if (pp->p_size) {
  1013. if (display_in_cyl_units && lp->d_secpercyl) {
  1014. printf(" %c: %8ld%c %8ld%c %8ld%c ",
  1015. 'a' + i,
  1016. (long) pp->p_offset / lp->d_secpercyl + 1,
  1017. (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
  1018. (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
  1019. / lp->d_secpercyl,
  1020. ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
  1021. (long) pp->p_size / lp->d_secpercyl,
  1022. (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
  1023. } else {
  1024. printf(" %c: %8ld %8ld %8ld ",
  1025. 'a' + i,
  1026. (long) pp->p_offset,
  1027. (long) pp->p_offset + pp->p_size - 1,
  1028. (long) pp->p_size);
  1029. }
  1030. if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
  1031. printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
  1032. else
  1033. printf("%8x", pp->p_fstype);
  1034. switch (pp->p_fstype) {
  1035. case BSD_FS_UNUSED:
  1036. printf(" %5ld %5ld %5.5s ",
  1037. (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
  1038. break;
  1039. case BSD_FS_BSDFFS:
  1040. printf(" %5ld %5ld %5d ",
  1041. (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
  1042. pp->p_cpg);
  1043. break;
  1044. default:
  1045. printf("%22.22s", "");
  1046. break;
  1047. }
  1048. printf("\n");
  1049. }
  1050. }
  1051. }
  1052. static void
  1053. xbsd_write_disklabel (void) {
  1054. #if defined (__alpha__)
  1055. printf (_("Writing disklabel to %s.\n"), disk_device);
  1056. xbsd_writelabel (NULL, &xbsd_dlabel);
  1057. #else
  1058. printf (_("Writing disklabel to %s.\n"),
  1059. partname(disk_device, xbsd_part_index+1, 0));
  1060. xbsd_writelabel (xbsd_part, &xbsd_dlabel);
  1061. #endif
  1062. reread_partition_table(0); /* no exit yet */
  1063. }
  1064. static int
  1065. xbsd_create_disklabel (void) {
  1066. char c;
  1067. #if defined (__alpha__)
  1068. fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
  1069. #else
  1070. fprintf (stderr, _("%s contains no disklabel.\n"),
  1071. partname(disk_device, xbsd_part_index+1, 0));
  1072. #endif
  1073. while (1) {
  1074. c = read_char (_("Do you want to create a disklabel? (y/n) "));
  1075. if (c == 'y' || c == 'Y') {
  1076. if (xbsd_initlabel (
  1077. #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
  1078. defined (__s390__) || defined (__s390x__)
  1079. NULL, &xbsd_dlabel, 0
  1080. #else
  1081. xbsd_part, &xbsd_dlabel, xbsd_part_index
  1082. #endif
  1083. ) == 1) {
  1084. xbsd_print_disklabel (1);
  1085. return 1;
  1086. } else
  1087. return 0;
  1088. } else if (c == 'n')
  1089. return 0;
  1090. }
  1091. }
  1092. static int
  1093. edit_int (int def, char *mesg)
  1094. {
  1095. do {
  1096. fputs (mesg, stdout);
  1097. printf (" (%d): ", def);
  1098. if (!read_line ())
  1099. return def;
  1100. }
  1101. while (!isdigit (*line_ptr));
  1102. return atoi (line_ptr);
  1103. }
  1104. static void
  1105. xbsd_edit_disklabel (void)
  1106. {
  1107. struct xbsd_disklabel *d;
  1108. d = &xbsd_dlabel;
  1109. #if defined (__alpha__) || defined (__ia64__)
  1110. d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
  1111. d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
  1112. d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
  1113. d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
  1114. #endif
  1115. /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
  1116. while (1)
  1117. {
  1118. d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
  1119. _("sectors/cylinder"));
  1120. if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
  1121. break;
  1122. printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
  1123. }
  1124. d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
  1125. d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
  1126. d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
  1127. d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
  1128. d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
  1129. d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
  1130. d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
  1131. }
  1132. static int
  1133. xbsd_get_bootstrap (char *path, void *ptr, int size)
  1134. {
  1135. int fdb;
  1136. if ((fdb = open (path, O_RDONLY)) < 0)
  1137. {
  1138. perror (path);
  1139. return 0;
  1140. }
  1141. if (read (fdb, ptr, size) < 0)
  1142. {
  1143. perror (path);
  1144. close (fdb);
  1145. return 0;
  1146. }
  1147. printf (" ... %s\n", path);
  1148. close (fdb);
  1149. return 1;
  1150. }
  1151. static void
  1152. sync_disks (void)
  1153. {
  1154. printf (_("\nSyncing disks.\n"));
  1155. sync ();
  1156. sleep (4);
  1157. }
  1158. static void
  1159. xbsd_write_bootstrap (void)
  1160. {
  1161. char *bootdir = BSD_LINUX_BOOTDIR;
  1162. char path[MAXPATHLEN];
  1163. char *dkbasename;
  1164. struct xbsd_disklabel dl;
  1165. char *d, *p, *e;
  1166. int sector;
  1167. if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
  1168. dkbasename = "sd";
  1169. else
  1170. dkbasename = "wd";
  1171. printf (_("Bootstrap: %sboot -> boot%s (%s): "),
  1172. dkbasename, dkbasename, dkbasename);
  1173. if (read_line ()) {
  1174. line_ptr[strlen (line_ptr)-1] = '\0';
  1175. dkbasename = line_ptr;
  1176. }
  1177. snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
  1178. if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
  1179. return;
  1180. /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
  1181. d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
  1182. bcopy (d, &dl, sizeof (struct xbsd_disklabel));
  1183. /* The disklabel will be overwritten by 0's from bootxx anyway */
  1184. bzero (d, sizeof (struct xbsd_disklabel));
  1185. snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
  1186. if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
  1187. (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
  1188. return;
  1189. e = d + sizeof (struct xbsd_disklabel);
  1190. for (p=d; p < e; p++)
  1191. if (*p) {
  1192. fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
  1193. exit ( EXIT_FAILURE );
  1194. }
  1195. bcopy (&dl, d, sizeof (struct xbsd_disklabel));
  1196. #if defined (__powerpc__) || defined (__hppa__)
  1197. sector = 0;
  1198. #elif defined (__alpha__)
  1199. sector = 0;
  1200. alpha_bootblock_checksum (disklabelbuffer);
  1201. #else
  1202. sector = get_start_sect(xbsd_part);
  1203. #endif
  1204. if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
  1205. fdisk_fatal (unable_to_seek);
  1206. if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
  1207. fdisk_fatal (unable_to_write);
  1208. #if defined (__alpha__)
  1209. printf (_("Bootstrap installed on %s.\n"), disk_device);
  1210. #else
  1211. printf (_("Bootstrap installed on %s.\n"),
  1212. partname (disk_device, xbsd_part_index+1, 0));
  1213. #endif
  1214. sync_disks ();
  1215. }
  1216. static void
  1217. xbsd_change_fstype (void)
  1218. {
  1219. int i;
  1220. i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
  1221. xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
  1222. }
  1223. static int
  1224. xbsd_get_part_index (int max)
  1225. {
  1226. char prompt[256];
  1227. char l;
  1228. snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
  1229. do
  1230. l = tolower (read_char (prompt));
  1231. while (l < 'a' || l > 'a' + max - 1);
  1232. return l - 'a';
  1233. }
  1234. static int
  1235. xbsd_check_new_partition (int *i) {
  1236. /* room for more? various BSD flavours have different maxima */
  1237. if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
  1238. int t;
  1239. for (t = 0; t < BSD_MAXPARTITIONS; t++)
  1240. if (xbsd_dlabel.d_partitions[t].p_size == 0)
  1241. break;
  1242. if (t == BSD_MAXPARTITIONS) {
  1243. fprintf (stderr, _("The maximum number of partitions "
  1244. "has been created\n"));
  1245. return 0;
  1246. }
  1247. }
  1248. *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
  1249. if (*i >= xbsd_dlabel.d_npartitions)
  1250. xbsd_dlabel.d_npartitions = (*i) + 1;
  1251. if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
  1252. fprintf (stderr, _("This partition already exists.\n"));
  1253. return 0;
  1254. }
  1255. return 1;
  1256. }
  1257. static void
  1258. xbsd_list_types (void) {
  1259. list_types (xbsd_fstypes);
  1260. }
  1261. static u_short
  1262. xbsd_dkcksum (struct xbsd_disklabel *lp) {
  1263. u_short *start, *end;
  1264. u_short sum = 0;
  1265. start = (u_short *) lp;
  1266. end = (u_short *) &lp->d_partitions[lp->d_npartitions];
  1267. while (start < end)
  1268. sum ^= *start++;
  1269. return sum;
  1270. }
  1271. static int
  1272. xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
  1273. struct xbsd_partition *pp;
  1274. get_geometry ();
  1275. bzero (d, sizeof (struct xbsd_disklabel));
  1276. d -> d_magic = BSD_DISKMAGIC;
  1277. if (strncmp (disk_device, "/dev/sd", 7) == 0)
  1278. d -> d_type = BSD_DTYPE_SCSI;
  1279. else
  1280. d -> d_type = BSD_DTYPE_ST506;
  1281. #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
  1282. d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
  1283. #endif
  1284. #if !defined (__alpha__)
  1285. d -> d_flags = BSD_D_DOSPART;
  1286. #else
  1287. d -> d_flags = 0;
  1288. #endif
  1289. d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
  1290. d -> d_nsectors = sectors; /* sectors/track */
  1291. d -> d_ntracks = heads; /* tracks/cylinder (heads) */
  1292. d -> d_ncylinders = cylinders;
  1293. d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
  1294. if (d -> d_secpercyl == 0)
  1295. d -> d_secpercyl = 1; /* avoid segfaults */
  1296. d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
  1297. d -> d_rpm = 3600;
  1298. d -> d_interleave = 1;
  1299. d -> d_trackskew = 0;
  1300. d -> d_cylskew = 0;
  1301. d -> d_headswitch = 0;
  1302. d -> d_trkseek = 0;
  1303. d -> d_magic2 = BSD_DISKMAGIC;
  1304. d -> d_bbsize = BSD_BBSIZE;
  1305. d -> d_sbsize = BSD_SBSIZE;
  1306. #if !defined (__alpha__)
  1307. d -> d_npartitions = 4;
  1308. pp = &d -> d_partitions[2]; /* Partition C should be
  1309. the NetBSD partition */
  1310. pp -> p_offset = get_start_sect(p);
  1311. pp -> p_size = get_nr_sects(p);
  1312. pp -> p_fstype = BSD_FS_UNUSED;
  1313. pp = &d -> d_partitions[3]; /* Partition D should be
  1314. the whole disk */
  1315. pp -> p_offset = 0;
  1316. pp -> p_size = d -> d_secperunit;
  1317. pp -> p_fstype = BSD_FS_UNUSED;
  1318. #elif defined (__alpha__)
  1319. d -> d_npartitions = 3;
  1320. pp = &d -> d_partitions[2]; /* Partition C should be
  1321. the whole disk */
  1322. pp -> p_offset = 0;
  1323. pp -> p_size = d -> d_secperunit;
  1324. pp -> p_fstype = BSD_FS_UNUSED;
  1325. #endif
  1326. return 1;
  1327. }
  1328. /*
  1329. * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
  1330. * If it has the right magic, return 1.
  1331. */
  1332. static int
  1333. xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
  1334. {
  1335. int t, sector;
  1336. /* p is used only to get the starting sector */
  1337. #if !defined (__alpha__)
  1338. sector = (p ? get_start_sect(p) : 0);
  1339. #elif defined (__alpha__)
  1340. sector = 0;
  1341. #endif
  1342. if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
  1343. fdisk_fatal (unable_to_seek);
  1344. if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
  1345. fdisk_fatal (unable_to_read);
  1346. bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
  1347. d, sizeof (struct xbsd_disklabel));
  1348. if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
  1349. return 0;
  1350. for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
  1351. d -> d_partitions[t].p_size = 0;
  1352. d -> d_partitions[t].p_offset = 0;
  1353. d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
  1354. }
  1355. if (d -> d_npartitions > BSD_MAXPARTITIONS)
  1356. fprintf (stderr, _("Warning: too many partitions "
  1357. "(%d, maximum is %d).\n"),
  1358. d -> d_npartitions, BSD_MAXPARTITIONS);
  1359. return 1;
  1360. }
  1361. static int
  1362. xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
  1363. {
  1364. unsigned int sector;
  1365. #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
  1366. sector = get_start_sect(p) + BSD_LABELSECTOR;
  1367. #else
  1368. sector = BSD_LABELSECTOR;
  1369. #endif
  1370. d -> d_checksum = 0;
  1371. d -> d_checksum = xbsd_dkcksum (d);
  1372. /* This is necessary if we want to write the bootstrap later,
  1373. otherwise we'd write the old disklabel with the bootstrap.
  1374. */
  1375. bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
  1376. sizeof (struct xbsd_disklabel));
  1377. #if defined (__alpha__) && BSD_LABELSECTOR == 0
  1378. alpha_bootblock_checksum (disklabelbuffer);
  1379. if (lseek (fd, 0, SEEK_SET) == -1)
  1380. fdisk_fatal (unable_to_seek);
  1381. if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
  1382. fdisk_fatal (unable_to_write);
  1383. #else
  1384. if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
  1385. SEEK_SET) == -1)
  1386. fdisk_fatal (unable_to_seek);
  1387. if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
  1388. fdisk_fatal (unable_to_write);
  1389. #endif
  1390. sync_disks ();
  1391. return 1;
  1392. }
  1393. #if !defined (__alpha__)
  1394. static int
  1395. xbsd_translate_fstype (int linux_type)
  1396. {
  1397. switch (linux_type)
  1398. {
  1399. case 0x01: /* DOS 12-bit FAT */
  1400. case 0x04: /* DOS 16-bit <32M */
  1401. case 0x06: /* DOS 16-bit >=32M */
  1402. case 0xe1: /* DOS access */
  1403. case 0xe3: /* DOS R/O */
  1404. case 0xf2: /* DOS secondary */
  1405. return BSD_FS_MSDOS;
  1406. case 0x07: /* OS/2 HPFS */
  1407. return BSD_FS_HPFS;
  1408. default:
  1409. return BSD_FS_OTHER;
  1410. }
  1411. }
  1412. static void
  1413. xbsd_link_part (void)
  1414. {
  1415. int k, i;
  1416. struct partition *p;
  1417. k = get_partition (1, partitions);
  1418. if (!xbsd_check_new_partition (&i))
  1419. return;
  1420. p = get_part_table(k);
  1421. xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
  1422. xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
  1423. xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
  1424. }
  1425. #endif
  1426. #if defined (__alpha__)
  1427. #if !defined(__GLIBC__)
  1428. typedef unsigned long long uint64_t;
  1429. #endif
  1430. static void
  1431. alpha_bootblock_checksum (char *boot)
  1432. {
  1433. uint64_t *dp, sum;
  1434. int i;
  1435. dp = (uint64_t *)boot;
  1436. sum = 0;
  1437. for (i = 0; i < 63; i++)
  1438. sum += dp[i];
  1439. dp[63] = sum;
  1440. }
  1441. #endif /* __alpha__ */
  1442. #endif /* OSF_LABEL */
  1443. #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
  1444. static inline unsigned short
  1445. __swap16(unsigned short x) {
  1446. return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
  1447. }
  1448. static inline uint32_t
  1449. __swap32(uint32_t x) {
  1450. return (((x & 0xFF) << 24) |
  1451. ((x & 0xFF00) << 8) |
  1452. ((x & 0xFF0000) >> 8) |
  1453. ((x & 0xFF000000) >> 24));
  1454. }
  1455. #endif
  1456. #ifdef CONFIG_FEATURE_SGI_LABEL
  1457. /*
  1458. *
  1459. * fdisksgilabel.c
  1460. *
  1461. * Copyright (C) Andreas Neuper, Sep 1998.
  1462. * This file may be modified and redistributed under
  1463. * the terms of the GNU Public License.
  1464. *
  1465. * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  1466. * Internationalization
  1467. */
  1468. static int sgi_other_endian;
  1469. static int debug;
  1470. static short sgi_volumes=1;
  1471. /*
  1472. * only dealing with free blocks here
  1473. */
  1474. typedef struct { unsigned int first; unsigned int last; } freeblocks;
  1475. static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
  1476. static void
  1477. setfreelist(int i, unsigned int f, unsigned int l) {
  1478. freelist[i].first = f;
  1479. freelist[i].last = l;
  1480. }
  1481. static void
  1482. add2freelist(unsigned int f, unsigned int l) {
  1483. int i = 0;
  1484. for ( ; i < 17 ; i++)
  1485. if (freelist[i].last == 0)
  1486. break;
  1487. setfreelist(i, f, l);
  1488. }
  1489. static void
  1490. clearfreelist(void) {
  1491. int i;
  1492. for (i = 0; i < 17 ; i++)
  1493. setfreelist(i, 0, 0);
  1494. }
  1495. static unsigned int
  1496. isinfreelist(unsigned int b) {
  1497. int i;
  1498. for (i = 0; i < 17 ; i++)
  1499. if (freelist[i].first <= b && freelist[i].last >= b)
  1500. return freelist[i].last;
  1501. return 0;
  1502. }
  1503. /* return last vacant block of this stride (never 0). */
  1504. /* the '>=' is not quite correct, but simplifies the code */
  1505. /*
  1506. * end of free blocks section
  1507. */
  1508. static const struct systypes sgi_sys_types[] = {
  1509. /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
  1510. /* 0x01 */ {"\x01" "SGI trkrepl" },
  1511. /* 0x02 */ {"\x02" "SGI secrepl" },
  1512. /* SGI_SWAP */ {"\x03" "SGI raw" },
  1513. /* 0x04 */ {"\x04" "SGI bsd" },
  1514. /* 0x05 */ {"\x05" "SGI sysv" },
  1515. /* ENTIRE_DISK */ {"\x06" "SGI volume" },
  1516. /* SGI_EFS */ {"\x07" "SGI efs" },
  1517. /* 0x08 */ {"\x08" "SGI lvol" },
  1518. /* 0x09 */ {"\x09" "SGI rlvol" },
  1519. /* SGI_XFS */ {"\x0a" "SGI xfs" },
  1520. /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
  1521. /* SGI_XLV */ {"\x0c" "SGI xlv" },
  1522. /* SGI_XVM */ {"\x0d" "SGI xvm" },
  1523. /* LINUX_SWAP */ {"\x82" "Linux swap" },
  1524. /* LINUX_NATIVE */ {"\x83" "Linux native" },
  1525. /* LINUX_LVM */ {"\x8d" "Linux LVM" },
  1526. /* LINUX_RAID */ {"\xfd" "Linux RAID" },
  1527. { NULL }
  1528. };
  1529. static int
  1530. sgi_get_nsect(void) {
  1531. return SGI_SSWAP16(sgilabel->devparam.nsect);
  1532. }
  1533. static int
  1534. sgi_get_ntrks(void) {
  1535. return SGI_SSWAP16(sgilabel->devparam.ntrks);
  1536. }
  1537. static void
  1538. sgi_nolabel(void) {
  1539. sgilabel->magic = 0;
  1540. sgi_label = 0;
  1541. partitions = 4;
  1542. }
  1543. static unsigned int
  1544. two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
  1545. int i=0;
  1546. unsigned int sum=0;
  1547. size /= sizeof(unsigned int);
  1548. for (i = 0; i < size; i++)
  1549. sum -= SGI_SSWAP32(base[i]);
  1550. return sum;
  1551. }
  1552. static int
  1553. check_sgi_label(void) {
  1554. if (sizeof(sgilabel) > 512) {
  1555. fprintf(stderr,
  1556. _("According to MIPS Computer Systems, Inc the "
  1557. "Label must not contain more than 512 bytes\n"));
  1558. exit(1);
  1559. }
  1560. if (sgilabel->magic != SGI_LABEL_MAGIC &&
  1561. sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
  1562. sgi_label = 0;
  1563. sgi_other_endian = 0;
  1564. return 0;
  1565. }
  1566. sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
  1567. /*
  1568. * test for correct checksum
  1569. */
  1570. if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
  1571. sizeof(*sgilabel))) {
  1572. fprintf(stderr,
  1573. _("Detected sgi disklabel with wrong checksum.\n"));
  1574. }
  1575. update_units();
  1576. sgi_label = 1;
  1577. partitions= 16;
  1578. sgi_volumes = 15;
  1579. return 1;
  1580. }
  1581. static unsigned int
  1582. sgi_get_start_sector(int i) {
  1583. return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
  1584. }
  1585. static unsigned int
  1586. sgi_get_num_sectors(int i) {
  1587. return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
  1588. }
  1589. static int
  1590. sgi_get_sysid(int i)
  1591. {
  1592. return SGI_SSWAP32(sgilabel->partitions[i].id);
  1593. }
  1594. static int
  1595. sgi_get_bootpartition(void)
  1596. {
  1597. return SGI_SSWAP16(sgilabel->boot_part);
  1598. }
  1599. static int
  1600. sgi_get_swappartition(void)
  1601. {
  1602. return SGI_SSWAP16(sgilabel->swap_part);
  1603. }
  1604. static void
  1605. sgi_list_table(int xtra) {
  1606. int i, w, wd;
  1607. int kpi = 0; /* kernel partition ID */
  1608. if(xtra) {
  1609. printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
  1610. "%d cylinders, %d physical cylinders\n"
  1611. "%d extra sects/cyl, interleave %d:1\n"
  1612. "%s\n"
  1613. "Units = %s of %d * 512 bytes\n\n"),
  1614. disk_device, heads, sectors, cylinders,
  1615. SGI_SSWAP16(sgiparam.pcylcount),
  1616. SGI_SSWAP16(sgiparam.sparecyl),
  1617. SGI_SSWAP16(sgiparam.ilfact),
  1618. (char *)sgilabel,
  1619. str_units(PLURAL), units_per_sector);
  1620. } else {
  1621. printf( _("\nDisk %s (SGI disk label): "
  1622. "%d heads, %d sectors, %d cylinders\n"
  1623. "Units = %s of %d * 512 bytes\n\n"),
  1624. disk_device, heads, sectors, cylinders,
  1625. str_units(PLURAL), units_per_sector );
  1626. }
  1627. w = strlen(disk_device);
  1628. wd = strlen(_("Device"));
  1629. if (w < wd)
  1630. w = wd;
  1631. printf(_("----- partitions -----\n"
  1632. "Pt# %*s Info Start End Sectors Id System\n"),
  1633. w + 2, _("Device"));
  1634. for (i = 0 ; i < partitions; i++) {
  1635. if( sgi_get_num_sectors(i) || debug ) {
  1636. uint32_t start = sgi_get_start_sector(i);
  1637. uint32_t len = sgi_get_num_sectors(i);
  1638. kpi++; /* only count nonempty partitions */
  1639. printf(
  1640. "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
  1641. /* fdisk part number */ i+1,
  1642. /* device */ partname(disk_device, kpi, w+3),
  1643. /* flags */ (sgi_get_swappartition() == i) ? "swap" :
  1644. /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
  1645. /* start */ (long) scround(start),
  1646. /* end */ (long) scround(start+len)-1,
  1647. /* no odd flag on end */ (long) len,
  1648. /* type id */ sgi_get_sysid(i),
  1649. /* type name */ partition_type(sgi_get_sysid(i)));
  1650. }
  1651. }
  1652. printf(_("----- Bootinfo -----\nBootfile: %s\n"
  1653. "----- Directory Entries -----\n"),
  1654. sgilabel->boot_file);
  1655. for (i = 0 ; i < sgi_volumes; i++) {
  1656. if (sgilabel->directory[i].vol_file_size) {
  1657. uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
  1658. uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
  1659. char*name = sgilabel->directory[i].vol_file_name;
  1660. printf(_("%2d: %-10s sector%5u size%8u\n"),
  1661. i, name, (unsigned int) start, (unsigned int) len);
  1662. }
  1663. }
  1664. }
  1665. static void
  1666. sgi_set_bootpartition( int i )
  1667. {
  1668. sgilabel->boot_part = SGI_SSWAP16(((short)i));
  1669. }
  1670. static unsigned int
  1671. sgi_get_lastblock(void) {
  1672. return heads * sectors * cylinders;
  1673. }
  1674. static void
  1675. sgi_set_swappartition( int i ) {
  1676. sgilabel->swap_part = SGI_SSWAP16(((short)i));
  1677. }
  1678. static int
  1679. sgi_check_bootfile(const char* aFile) {
  1680. if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
  1681. printf(_("\nInvalid Bootfile!\n"
  1682. "\tThe bootfile must be an absolute non-zero pathname,\n"
  1683. "\te.g. \"/unix\" or \"/unix.save\".\n"));
  1684. return 0;
  1685. } else {
  1686. if (strlen(aFile) > 16) {
  1687. printf(_("\n\tName of Bootfile too long: "
  1688. "16 bytes maximum.\n"));
  1689. return 0;
  1690. } else {
  1691. if (aFile[0] != '/') {
  1692. printf(_("\n\tBootfile must have a "
  1693. "fully qualified pathname.\n"));
  1694. return 0;
  1695. }
  1696. }
  1697. }
  1698. if (strncmp(aFile, sgilabel->boot_file, 16)) {
  1699. printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
  1700. "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
  1701. /* filename is correct and did change */
  1702. return 1;
  1703. }
  1704. return 0; /* filename did not change */
  1705. }
  1706. static const char *
  1707. sgi_get_bootfile(void) {
  1708. return sgilabel->boot_file;
  1709. }
  1710. static void
  1711. sgi_set_bootfile(const char* aFile) {
  1712. int i = 0;
  1713. if (sgi_check_bootfile(aFile)) {
  1714. while (i < 16) {
  1715. if ((aFile[i] != '\n') /* in principle caught again by next line */
  1716. && (strlen(aFile) > i))
  1717. sgilabel->boot_file[i] = aFile[i];
  1718. else
  1719. sgilabel->boot_file[i] = 0;
  1720. i++;
  1721. }
  1722. printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
  1723. }
  1724. }
  1725. static void
  1726. create_sgiinfo(void)
  1727. {
  1728. /* I keep SGI's habit to write the sgilabel to the second block */
  1729. sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
  1730. sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
  1731. strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
  1732. }
  1733. static sgiinfo *fill_sgiinfo(void);
  1734. static void
  1735. sgi_write_table(void) {
  1736. sgilabel->csum = 0;
  1737. sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
  1738. (unsigned int*)sgilabel,
  1739. sizeof(*sgilabel)));
  1740. assert(two_s_complement_32bit_sum(
  1741. (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
  1742. if (lseek(fd, 0, SEEK_SET) < 0)
  1743. fdisk_fatal(unable_to_seek);
  1744. if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
  1745. fdisk_fatal(unable_to_write);
  1746. if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
  1747. /*
  1748. * keep this habit of first writing the "sgilabel".
  1749. * I never tested whether it works without (AN 981002).
  1750. */
  1751. sgiinfo *info = fill_sgiinfo();
  1752. int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
  1753. if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
  1754. fdisk_fatal(unable_to_seek);
  1755. if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
  1756. fdisk_fatal(unable_to_write);
  1757. free(info);
  1758. }
  1759. }
  1760. static int
  1761. compare_start(int *x, int *y) {
  1762. /*
  1763. * sort according to start sectors
  1764. * and prefers largest partition:
  1765. * entry zero is entire disk entry
  1766. */
  1767. unsigned int i = *x;
  1768. unsigned int j = *y;
  1769. unsigned int a = sgi_get_start_sector(i);
  1770. unsigned int b = sgi_get_start_sector(j);
  1771. unsigned int c = sgi_get_num_sectors(i);
  1772. unsigned int d = sgi_get_num_sectors(j);
  1773. if (a == b)
  1774. return (d > c) ? 1 : (d == c) ? 0 : -1;
  1775. return (a > b) ? 1 : -1;
  1776. }
  1777. static int
  1778. verify_sgi(int verbose)
  1779. {
  1780. int Index[16]; /* list of valid partitions */
  1781. int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
  1782. int entire = 0, i = 0;
  1783. unsigned int start = 0;
  1784. long long gap = 0; /* count unused blocks */
  1785. unsigned int lastblock = sgi_get_lastblock();
  1786. clearfreelist();
  1787. for (i=0; i<16; i++) {
  1788. if (sgi_get_num_sectors(i) != 0) {
  1789. Index[sortcount++]=i;
  1790. if (sgi_get_sysid(i) == ENTIRE_DISK) {
  1791. if (entire++ == 1) {
  1792. if (verbose)
  1793. printf(_("More than one entire disk entry present.\n"));
  1794. }
  1795. }
  1796. }
  1797. }
  1798. if (sortcount == 0) {
  1799. if (verbose)
  1800. printf(_("No partitions defined\n"));
  1801. return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
  1802. }
  1803. qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
  1804. if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
  1805. if ((Index[0] != 10) && verbose)
  1806. printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
  1807. if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
  1808. printf(_("The entire disk partition should start "
  1809. "at block 0,\n"
  1810. "not at diskblock %d.\n"),
  1811. sgi_get_start_sector(Index[0]));
  1812. if (debug) /* I do not understand how some disks fulfil it */
  1813. if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
  1814. printf(_("The entire disk partition is only %d diskblock large,\n"
  1815. "but the disk is %d diskblocks long.\n"),
  1816. sgi_get_num_sectors(Index[0]), lastblock);
  1817. lastblock = sgi_get_num_sectors(Index[0]);
  1818. } else {
  1819. if (verbose)
  1820. printf(_("One Partition (#11) should cover the entire disk.\n"));
  1821. if (debug>2)
  1822. printf("sysid=%d\tpartition=%d\n",
  1823. sgi_get_sysid(Index[0]), Index[0]+1);
  1824. }
  1825. for (i=1, start=0; i<sortcount; i++) {
  1826. int cylsize = sgi_get_nsect() * sgi_get_ntrks();
  1827. if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
  1828. if (debug) /* I do not understand how some disks fulfil it */
  1829. if (verbose)
  1830. printf(_("Partition %d does not start on cylinder boundary.\n"),
  1831. Index[i]+1);
  1832. }
  1833. if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
  1834. if (debug) /* I do not understand how some disks fulfil it */
  1835. if (verbose)
  1836. printf(_("Partition %d does not end on cylinder boundary.\n"),
  1837. Index[i]+1);
  1838. }
  1839. /* We cannot handle several "entire disk" entries. */
  1840. if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
  1841. if (start > sgi_get_start_sector(Index[i])) {
  1842. if (verbose)
  1843. printf(_("The Partition %d and %d overlap by %d sectors.\n"),
  1844. Index[i-1]+1, Index[i]+1,
  1845. start - sgi_get_start_sector(Index[i]));
  1846. if (gap > 0) gap = -gap;
  1847. if (gap == 0) gap = -1;
  1848. }
  1849. if (start < sgi_get_start_sector(Index[i])) {
  1850. if (verbose)
  1851. printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
  1852. sgi_get_start_sector(Index[i]) - start,
  1853. start, sgi_get_start_sector(Index[i])-1);
  1854. gap += sgi_get_start_sector(Index[i]) - start;
  1855. add2freelist(start, sgi_get_start_sector(Index[i]));
  1856. }
  1857. start = sgi_get_start_sector(Index[i])
  1858. + sgi_get_num_sectors(Index[i]);
  1859. if (debug > 1) {
  1860. if (verbose)
  1861. printf("%2d:%12d\t%12d\t%12d\n", Index[i],
  1862. sgi_get_start_sector(Index[i]),
  1863. sgi_get_num_sectors(Index[i]),
  1864. sgi_get_sysid(Index[i]));
  1865. }
  1866. }
  1867. if (start < lastblock) {
  1868. if (verbose)
  1869. printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
  1870. lastblock - start, start, lastblock-1);
  1871. gap += lastblock - start;
  1872. add2freelist(start, lastblock);
  1873. }
  1874. /*
  1875. * Done with arithmetics
  1876. * Go for details now
  1877. */
  1878. if (verbose) {
  1879. if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
  1880. printf(_("\nThe boot partition does not exist.\n"));
  1881. }
  1882. if (!sgi_get_num_sectors(sgi_get_swappartition())) {
  1883. printf(_("\nThe swap partition does not exist.\n"));
  1884. } else {
  1885. if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
  1886. && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
  1887. printf(_("\nThe swap partition has no swap type.\n"));
  1888. }
  1889. if (sgi_check_bootfile("/unix"))
  1890. printf(_("\tYou have chosen an unusual boot file name.\n"));
  1891. }
  1892. return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
  1893. }
  1894. static int
  1895. sgi_gaps(void) {
  1896. /*
  1897. * returned value is:
  1898. * = 0 : disk is properly filled to the rim
  1899. * < 0 : there is an overlap
  1900. * > 0 : there is still some vacant space
  1901. */
  1902. return verify_sgi(0);
  1903. }
  1904. static void
  1905. sgi_change_sysid( int i, int sys )
  1906. {
  1907. if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
  1908. {
  1909. printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
  1910. return;
  1911. }
  1912. if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
  1913. && (sgi_get_start_sector(i)<1) )
  1914. {
  1915. read_chars(
  1916. _("It is highly recommended that the partition at offset 0\n"
  1917. "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
  1918. "retrieve from its directory standalone tools like sash and fx.\n"
  1919. "Only the \"SGI volume\" entire disk section may violate this.\n"
  1920. "Type YES if you are sure about tagging this partition differently.\n"));
  1921. if (strcmp (line_ptr, _("YES\n")))
  1922. return;
  1923. }
  1924. sgilabel->partitions[i].id = SGI_SSWAP32(sys);
  1925. }
  1926. /* returns partition index of first entry marked as entire disk */
  1927. static int
  1928. sgi_entire(void) {
  1929. int i;
  1930. for(i=0; i<16; i++)
  1931. if(sgi_get_sysid(i) == SGI_VOLUME)
  1932. return i;
  1933. return -1;
  1934. }
  1935. static void
  1936. sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
  1937. sgilabel->partitions[i].id = SGI_SSWAP32(sys);
  1938. sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
  1939. sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
  1940. set_changed(i);
  1941. if (sgi_gaps() < 0) /* rebuild freelist */
  1942. printf(_("Do You know, You got a partition overlap on the disk?\n"));
  1943. }
  1944. static void
  1945. sgi_set_entire(void) {
  1946. int n;
  1947. for(n=10; n < partitions; n++) {
  1948. if(!sgi_get_num_sectors(n) ) {
  1949. sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
  1950. break;
  1951. }
  1952. }
  1953. }
  1954. static void
  1955. sgi_set_volhdr(void)
  1956. {
  1957. int n;
  1958. for( n=8; n<partitions; n++ )
  1959. {
  1960. if(!sgi_get_num_sectors( n ) )
  1961. {
  1962. /*
  1963. * 5 cylinders is an arbitrary value I like
  1964. * IRIX 5.3 stored files in the volume header
  1965. * (like sash, symmon, fx, ide) with ca. 3200
  1966. * sectors.
  1967. */
  1968. if( heads * sectors * 5 < sgi_get_lastblock() )
  1969. sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
  1970. break;
  1971. }
  1972. }
  1973. }
  1974. static void
  1975. sgi_delete_partition( int i )
  1976. {
  1977. sgi_set_partition( i, 0, 0, 0 );
  1978. }
  1979. static void
  1980. sgi_add_partition( int n, int sys )
  1981. {
  1982. char mesg[256];
  1983. unsigned int first=0, last=0;
  1984. if( n == 10 ) {
  1985. sys = SGI_VOLUME;
  1986. } else if ( n == 8 ) {
  1987. sys = 0;
  1988. }
  1989. if(sgi_get_num_sectors(n)) {
  1990. printf(_("Partition %d is already defined. Delete "
  1991. "it before re-adding it.\n"), n + 1);
  1992. return;
  1993. }
  1994. if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
  1995. printf(_("Attempting to generate entire disk entry automatically.\n"));
  1996. sgi_set_entire();
  1997. sgi_set_volhdr();
  1998. }
  1999. if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
  2000. printf(_("The entire disk is already covered with partitions.\n"));
  2001. return;
  2002. }
  2003. if(sgi_gaps() < 0) {
  2004. printf(_("You got a partition overlap on the disk. Fix it first!\n"));
  2005. return;
  2006. }
  2007. snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
  2008. for(;;) {
  2009. if(sys == SGI_VOLUME) {
  2010. last = sgi_get_lastblock();
  2011. first = read_int(0, 0, last-1, 0, mesg);
  2012. if( first != 0 ) {
  2013. printf(_("It is highly recommended that eleventh partition\n"
  2014. "covers the entire disk and is of type `SGI volume'\n"));
  2015. }
  2016. } else {
  2017. first = freelist[0].first;
  2018. last = freelist[0].last;
  2019. first = read_int(scround(first), scround(first), scround(last)-1,
  2020. 0, mesg);
  2021. }
  2022. if (display_in_cyl_units)
  2023. first *= units_per_sector;
  2024. else
  2025. first = first; /* align to cylinder if you know how ... */
  2026. if( !last )
  2027. last = isinfreelist(first);
  2028. if( last == 0 ) {
  2029. printf(_("You will get a partition overlap on the disk. "
  2030. "Fix it first!\n"));
  2031. } else
  2032. break;
  2033. }
  2034. snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
  2035. last = read_int(scround(first), scround(last)-1, scround(last)-1,
  2036. scround(first), mesg)+1;
  2037. if (display_in_cyl_units)
  2038. last *= units_per_sector;
  2039. else
  2040. last = last; /* align to cylinder if You know how ... */
  2041. if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
  2042. printf(_("It is highly recommended that eleventh partition\n"
  2043. "covers the entire disk and is of type `SGI volume'\n"));
  2044. sgi_set_partition( n, first, last-first, sys );
  2045. }
  2046. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  2047. static void
  2048. create_sgilabel(void)
  2049. {
  2050. struct hd_geometry geometry;
  2051. struct {
  2052. unsigned int start;
  2053. unsigned int nsect;
  2054. int sysid;
  2055. } old[4];
  2056. int i=0;
  2057. long longsectors; /* the number of sectors on the device */
  2058. int res; /* the result from the ioctl */
  2059. int sec_fac; /* the sector factor */
  2060. sec_fac = sector_size / 512; /* determine the sector factor */
  2061. fprintf( stderr,
  2062. _("Building a new SGI disklabel. Changes will remain in memory only,\n"
  2063. "until you decide to write them. After that, of course, the previous\n"
  2064. "content will be unrecoverably lost.\n\n"));
  2065. sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
  2066. res = ioctl(fd, BLKGETSIZE, &longsectors);
  2067. if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
  2068. heads = geometry.heads;
  2069. sectors = geometry.sectors;
  2070. if (res == 0) {
  2071. /* the get device size ioctl was successful */
  2072. cylinders = longsectors / (heads * sectors);
  2073. cylinders /= sec_fac;
  2074. } else {
  2075. /* otherwise print error and use truncated version */
  2076. cylinders = geometry.cylinders;
  2077. fprintf(stderr,
  2078. _("Warning: BLKGETSIZE ioctl failed on %s. "
  2079. "Using geometry cylinder value of %d.\n"
  2080. "This value may be truncated for devices"
  2081. " > 33.8 GB.\n"), disk_device, cylinders);
  2082. }
  2083. }
  2084. for (i = 0; i < 4; i++) {
  2085. old[i].sysid = 0;
  2086. if(valid_part_table_flag(MBRbuffer)) {
  2087. if(get_part_table(i)->sys_ind) {
  2088. old[i].sysid = get_part_table(i)->sys_ind;
  2089. old[i].start = get_start_sect(get_part_table(i));
  2090. old[i].nsect = get_nr_sects(get_part_table(i));
  2091. printf(_("Trying to keep parameters of partition %d.\n"), i);
  2092. if (debug)
  2093. printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
  2094. old[i].sysid, old[i].start, old[i].nsect);
  2095. }
  2096. }
  2097. }
  2098. memset(MBRbuffer, 0, sizeof(MBRbuffer));
  2099. sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
  2100. sgilabel->boot_part = SGI_SSWAP16(0);
  2101. sgilabel->swap_part = SGI_SSWAP16(1);
  2102. /* sizeof(sgilabel->boot_file) = 16 > 6 */
  2103. memset(sgilabel->boot_file, 0, 16);
  2104. strcpy(sgilabel->boot_file, "/unix");
  2105. sgilabel->devparam.skew = (0);
  2106. sgilabel->devparam.gap1 = (0);
  2107. sgilabel->devparam.gap2 = (0);
  2108. sgilabel->devparam.sparecyl = (0);
  2109. sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
  2110. sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
  2111. sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
  2112. /* tracks/cylinder (heads) */
  2113. sgilabel->devparam.cmd_tag_queue_depth = (0);
  2114. sgilabel->devparam.unused0 = (0);
  2115. sgilabel->devparam.unused1 = SGI_SSWAP16(0);
  2116. sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
  2117. /* sectors/track */
  2118. sgilabel->devparam.bytes = SGI_SSWAP16(512);
  2119. sgilabel->devparam.ilfact = SGI_SSWAP16(1);
  2120. sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
  2121. IGNORE_ERRORS|RESEEK);
  2122. sgilabel->devparam.datarate = SGI_SSWAP32(0);
  2123. sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
  2124. sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
  2125. sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
  2126. sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
  2127. sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
  2128. sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
  2129. sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
  2130. sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
  2131. memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
  2132. memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
  2133. sgi_label = 1;
  2134. partitions = 16;
  2135. sgi_volumes = 15;
  2136. sgi_set_entire();
  2137. sgi_set_volhdr();
  2138. for (i = 0; i < 4; i++) {
  2139. if(old[i].sysid) {
  2140. sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
  2141. }
  2142. }
  2143. }
  2144. static void
  2145. sgi_set_xcyl(void)
  2146. {
  2147. /* do nothing in the beginning */
  2148. }
  2149. #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
  2150. /* _____________________________________________________________
  2151. */
  2152. static sgiinfo *
  2153. fill_sgiinfo(void)
  2154. {
  2155. sgiinfo *info = calloc(1, sizeof(sgiinfo));
  2156. info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
  2157. info->b1=SGI_SSWAP32(-1);
  2158. info->b2=SGI_SSWAP16(-1);
  2159. info->b3=SGI_SSWAP16(1);
  2160. /* You may want to replace this string !!!!!!! */
  2161. strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
  2162. strcpy( info->serial, "0000" );
  2163. info->check1816 = SGI_SSWAP16(18*256 +16 );
  2164. strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
  2165. return info;
  2166. }
  2167. #endif /* SGI_LABEL */
  2168. #ifdef CONFIG_FEATURE_SUN_LABEL
  2169. /*
  2170. * fdisksunlabel.c
  2171. *
  2172. * I think this is mostly, or entirely, due to
  2173. * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
  2174. *
  2175. * Merged with fdisk for other architectures, aeb, June 1998.
  2176. *
  2177. * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  2178. * Internationalization
  2179. */
  2180. static int sun_other_endian;
  2181. static int scsi_disk;
  2182. static int floppy;
  2183. #ifndef IDE0_MAJOR
  2184. #define IDE0_MAJOR 3
  2185. #endif
  2186. #ifndef IDE1_MAJOR
  2187. #define IDE1_MAJOR 22
  2188. #endif
  2189. static void guess_device_type(void) {
  2190. struct stat bootstat;
  2191. if (fstat (fd, &bootstat) < 0) {
  2192. scsi_disk = 0;
  2193. floppy = 0;
  2194. } else if (S_ISBLK(bootstat.st_mode)
  2195. && (major(bootstat.st_rdev) == IDE0_MAJOR ||
  2196. major(bootstat.st_rdev) == IDE1_MAJOR)) {
  2197. scsi_disk = 0;
  2198. floppy = 0;
  2199. } else if (S_ISBLK(bootstat.st_mode)
  2200. && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
  2201. scsi_disk = 0;
  2202. floppy = 1;
  2203. } else {
  2204. scsi_disk = 1;
  2205. floppy = 0;
  2206. }
  2207. }
  2208. static const struct systypes sun_sys_types[] = {
  2209. /* 0 */ {"\x00" "Empty" },
  2210. /* 1 */ {"\x01" "Boot" },
  2211. /* 2 */ {"\x02" "SunOS root" },
  2212. /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
  2213. /* 4 */ {"\x04" "SunOS usr" },
  2214. /* WHOLE_DISK */ {"\x05" "Whole disk" },
  2215. /* 6 */ {"\x06" "SunOS stand" },
  2216. /* 7 */ {"\x07" "SunOS var" },
  2217. /* 8 */ {"\x08" "SunOS home" },
  2218. /* LINUX_SWAP */ {"\x82" "Linux swap" },
  2219. /* LINUX_NATIVE */ {"\x83" "Linux native" },
  2220. /* 0x8e */ {"\x8e" "Linux LVM" },
  2221. /* New (2.2.x) raid partition with autodetect using persistent superblock */
  2222. /* 0xfd */ {"\xfd" "Linux raid autodetect" },
  2223. { NULL }
  2224. };
  2225. static void
  2226. set_sun_partition(int i, uint start, uint stop, int sysid) {
  2227. sunlabel->infos[i].id = sysid;
  2228. sunlabel->partitions[i].start_cylinder =
  2229. SUN_SSWAP32(start / (heads * sectors));
  2230. sunlabel->partitions[i].num_sectors =
  2231. SUN_SSWAP32(stop - start);
  2232. set_changed(i);
  2233. }
  2234. static void
  2235. sun_nolabel(void) {
  2236. sun_label = 0;
  2237. sunlabel->magic = 0;
  2238. partitions = 4;
  2239. }
  2240. static int
  2241. check_sun_label(void) {
  2242. unsigned short *ush;
  2243. int csum;
  2244. if (sunlabel->magic != SUN_LABEL_MAGIC &&
  2245. sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
  2246. sun_label = 0;
  2247. sun_other_endian = 0;
  2248. return 0;
  2249. }
  2250. sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
  2251. ush = ((unsigned short *) (sunlabel + 1)) - 1;
  2252. for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
  2253. if (csum) {
  2254. fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
  2255. "Probably you'll have to set all the values,\n"
  2256. "e.g. heads, sectors, cylinders and partitions\n"
  2257. "or force a fresh label (s command in main menu)\n"));
  2258. } else {
  2259. heads = SUN_SSWAP16(sunlabel->ntrks);
  2260. cylinders = SUN_SSWAP16(sunlabel->ncyl);
  2261. sectors = SUN_SSWAP16(sunlabel->nsect);
  2262. }
  2263. update_units();
  2264. sun_label = 1;
  2265. partitions = 8;
  2266. return 1;
  2267. }
  2268. static const struct sun_predefined_drives {
  2269. const char *vendor;
  2270. const char *model;
  2271. unsigned short sparecyl;
  2272. unsigned short ncyl;
  2273. unsigned short nacyl;
  2274. unsigned short pcylcount;
  2275. unsigned short ntrks;
  2276. unsigned short nsect;
  2277. unsigned short rspeed;
  2278. } sun_drives[] = {
  2279. {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
  2280. {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
  2281. {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
  2282. {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
  2283. {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
  2284. {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
  2285. {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
  2286. {"","SUN0104",1,974,2,1019,6,35,3662},
  2287. {"","SUN0207",4,1254,2,1272,9,36,3600},
  2288. {"","SUN0327",3,1545,2,1549,9,46,3600},
  2289. {"","SUN0340",0,1538,2,1544,6,72,4200},
  2290. {"","SUN0424",2,1151,2,2500,9,80,4400},
  2291. {"","SUN0535",0,1866,2,2500,7,80,5400},
  2292. {"","SUN0669",5,1614,2,1632,15,54,3600},
  2293. {"","SUN1.0G",5,1703,2,1931,15,80,3597},
  2294. {"","SUN1.05",0,2036,2,2038,14,72,5400},
  2295. {"","SUN1.3G",6,1965,2,3500,17,80,5400},
  2296. {"","SUN2.1G",0,2733,2,3500,19,80,5400},
  2297. {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
  2298. };
  2299. static const struct sun_predefined_drives *
  2300. sun_autoconfigure_scsi(void) {
  2301. const struct sun_predefined_drives *p = NULL;
  2302. #ifdef SCSI_IOCTL_GET_IDLUN
  2303. unsigned int id[2];
  2304. char buffer[2048];
  2305. char buffer2[2048];
  2306. FILE *pfd;
  2307. char *vendor;
  2308. char *model;
  2309. char *q;
  2310. int i;
  2311. if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
  2312. sprintf(buffer,
  2313. "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
  2314. #if 0
  2315. ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
  2316. #else
  2317. /* This is very wrong (works only if you have one HBA),
  2318. but I haven't found a way how to get hostno
  2319. from the current kernel */
  2320. 0,
  2321. #endif
  2322. (id[0]>>16)&0xff,
  2323. id[0]&0xff,
  2324. (id[0]>>8)&0xff);
  2325. pfd = fopen("/proc/scsi/scsi","r");
  2326. if (pfd) {
  2327. while (fgets(buffer2,2048,pfd)) {
  2328. if (!strcmp(buffer, buffer2)) {
  2329. if (fgets(buffer2,2048,pfd)) {
  2330. q = strstr(buffer2,"Vendor: ");
  2331. if (q) {
  2332. q += 8;
  2333. vendor = q;
  2334. q = strstr(q," ");
  2335. *q++ = 0; /* truncate vendor name */
  2336. q = strstr(q,"Model: ");
  2337. if (q) {
  2338. *q = 0;
  2339. q += 7;
  2340. model = q;
  2341. q = strstr(q," Rev: ");
  2342. if (q) {
  2343. *q = 0;
  2344. for (i = 0; i < SIZE(sun_drives); i++) {
  2345. if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
  2346. continue;
  2347. if (!strstr(model, sun_drives[i].model))
  2348. continue;
  2349. printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
  2350. p = sun_drives + i;
  2351. break;
  2352. }
  2353. }
  2354. }
  2355. }
  2356. }
  2357. break;
  2358. }
  2359. }
  2360. fclose(pfd);
  2361. }
  2362. }
  2363. #endif
  2364. return p;
  2365. }
  2366. static void create_sunlabel(void)
  2367. {
  2368. struct hd_geometry geometry;
  2369. unsigned int ndiv;
  2370. int i;
  2371. unsigned char c;
  2372. const struct sun_predefined_drives *p = NULL;
  2373. fprintf(stderr,
  2374. _("Building a new sun disklabel. Changes will remain in memory only,\n"
  2375. "until you decide to write them. After that, of course, the previous\n"
  2376. "content won't be recoverable.\n\n"));
  2377. #if BYTE_ORDER == LITTLE_ENDIAN
  2378. sun_other_endian = 1;
  2379. #else
  2380. sun_other_endian = 0;
  2381. #endif
  2382. memset(MBRbuffer, 0, sizeof(MBRbuffer));
  2383. sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
  2384. if (!floppy) {
  2385. puts(_("Drive type\n"
  2386. " ? auto configure\n"
  2387. " 0 custom (with hardware detected defaults)"));
  2388. for (i = 0; i < SIZE(sun_drives); i++) {
  2389. printf(" %c %s%s%s\n",
  2390. i + 'a', sun_drives[i].vendor,
  2391. (*sun_drives[i].vendor) ? " " : "",
  2392. sun_drives[i].model);
  2393. }
  2394. for (;;) {
  2395. c = read_char(_("Select type (? for auto, 0 for custom): "));
  2396. if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
  2397. p = sun_drives + c - 'a';
  2398. break;
  2399. } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
  2400. p = sun_drives + c - 'A';
  2401. break;
  2402. } else if (c == '0') {
  2403. break;
  2404. } else if (c == '?' && scsi_disk) {
  2405. p = sun_autoconfigure_scsi();
  2406. if (!p)
  2407. printf(_("Autoconfigure failed.\n"));
  2408. else
  2409. break;
  2410. }
  2411. }
  2412. }
  2413. if (!p || floppy) {
  2414. if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
  2415. heads = geometry.heads;
  2416. sectors = geometry.sectors;
  2417. cylinders = geometry.cylinders;
  2418. } else {
  2419. heads = 0;
  2420. sectors = 0;
  2421. cylinders = 0;
  2422. }
  2423. if (floppy) {
  2424. sunlabel->nacyl = 0;
  2425. sunlabel->pcylcount = SUN_SSWAP16(cylinders);
  2426. sunlabel->rspeed = SUN_SSWAP16(300);
  2427. sunlabel->ilfact = SUN_SSWAP16(1);
  2428. sunlabel->sparecyl = 0;
  2429. } else {
  2430. heads = read_int(1,heads,1024,0,_("Heads"));
  2431. sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
  2432. if (cylinders)
  2433. cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
  2434. else
  2435. cylinders = read_int(1,0,65535,0,_("Cylinders"));
  2436. sunlabel->nacyl =
  2437. SUN_SSWAP16(read_int(0,2,65535,0,
  2438. _("Alternate cylinders")));
  2439. sunlabel->pcylcount =
  2440. SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
  2441. 65535,0,_("Physical cylinders")));
  2442. sunlabel->rspeed =
  2443. SUN_SSWAP16(read_int(1,5400,100000,0,
  2444. _("Rotation speed (rpm)")));
  2445. sunlabel->ilfact =
  2446. SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
  2447. sunlabel->sparecyl =
  2448. SUN_SSWAP16(read_int(0,0,sectors,0,
  2449. _("Extra sectors per cylinder")));
  2450. }
  2451. } else {
  2452. sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
  2453. sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
  2454. sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
  2455. sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
  2456. sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
  2457. sunlabel->nsect = SUN_SSWAP16(p->nsect);
  2458. sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
  2459. sunlabel->ilfact = SUN_SSWAP16(1);
  2460. cylinders = p->ncyl;
  2461. heads = p->ntrks;
  2462. sectors = p->nsect;
  2463. puts(_("You may change all the disk params from the x menu"));
  2464. }
  2465. snprintf(sunlabel->info, sizeof(sunlabel->info),
  2466. "%s%s%s cyl %d alt %d hd %d sec %d",
  2467. p ? p->vendor : "", (p && *p->vendor) ? " " : "",
  2468. p ? p->model
  2469. : (floppy ? _("3,5\" floppy") : _("Linux custom")),
  2470. cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
  2471. sunlabel->ntrks = SUN_SSWAP16(heads);
  2472. sunlabel->nsect = SUN_SSWAP16(sectors);
  2473. sunlabel->ncyl = SUN_SSWAP16(cylinders);
  2474. if (floppy)
  2475. set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
  2476. else {
  2477. if (cylinders * heads * sectors >= 150 * 2048) {
  2478. ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
  2479. } else
  2480. ndiv = cylinders * 2 / 3;
  2481. set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
  2482. set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
  2483. sunlabel->infos[1].flags |= 0x01; /* Not mountable */
  2484. }
  2485. set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
  2486. {
  2487. unsigned short *ush = (unsigned short *)sunlabel;
  2488. unsigned short csum = 0;
  2489. while(ush < (unsigned short *)(&sunlabel->csum))
  2490. csum ^= *ush++;
  2491. sunlabel->csum = csum;
  2492. }
  2493. set_all_unchanged();
  2494. set_changed(0);
  2495. get_boot(create_empty_sun);
  2496. }
  2497. static void
  2498. toggle_sunflags(int i, unsigned char mask) {
  2499. if (sunlabel->infos[i].flags & mask)
  2500. sunlabel->infos[i].flags &= ~mask;
  2501. else sunlabel->infos[i].flags |= mask;
  2502. set_changed(i);
  2503. }
  2504. static void
  2505. fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
  2506. int i, continuous = 1;
  2507. *start = 0; *stop = cylinders * heads * sectors;
  2508. for (i = 0; i < partitions; i++) {
  2509. if (sunlabel->partitions[i].num_sectors
  2510. && sunlabel->infos[i].id
  2511. && sunlabel->infos[i].id != WHOLE_DISK) {
  2512. starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
  2513. lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
  2514. if (continuous) {
  2515. if (starts[i] == *start)
  2516. *start += lens[i];
  2517. else if (starts[i] + lens[i] >= *stop)
  2518. *stop = starts[i];
  2519. else
  2520. continuous = 0;
  2521. /* There will be probably more gaps
  2522. than one, so lets check afterwards */
  2523. }
  2524. } else {
  2525. starts[i] = 0;
  2526. lens[i] = 0;
  2527. }
  2528. }
  2529. }
  2530. static uint *verify_sun_starts;
  2531. static int
  2532. verify_sun_cmp(int *a, int *b) {
  2533. if (*a == -1) return 1;
  2534. if (*b == -1) return -1;
  2535. if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
  2536. return -1;
  2537. }
  2538. static void
  2539. verify_sun(void) {
  2540. uint starts[8], lens[8], start, stop;
  2541. int i,j,k,starto,endo;
  2542. int array[8];
  2543. verify_sun_starts = starts;
  2544. fetch_sun(starts,lens,&start,&stop);
  2545. for (k = 0; k < 7; k++) {
  2546. for (i = 0; i < 8; i++) {
  2547. if (k && (lens[i] % (heads * sectors))) {
  2548. printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
  2549. }
  2550. if (lens[i]) {
  2551. for (j = 0; j < i; j++)
  2552. if (lens[j]) {
  2553. if (starts[j] == starts[i]+lens[i]) {
  2554. starts[j] = starts[i]; lens[j] += lens[i];
  2555. lens[i] = 0;
  2556. } else if (starts[i] == starts[j]+lens[j]){
  2557. lens[j] += lens[i];
  2558. lens[i] = 0;
  2559. } else if (!k) {
  2560. if (starts[i] < starts[j]+lens[j] &&
  2561. starts[j] < starts[i]+lens[i]) {
  2562. starto = starts[i];
  2563. if (starts[j] > starto)
  2564. starto = starts[j];
  2565. endo = starts[i]+lens[i];
  2566. if (starts[j]+lens[j] < endo)
  2567. endo = starts[j]+lens[j];
  2568. printf(_("Partition %d overlaps with others in "
  2569. "sectors %d-%d\n"), i+1, starto, endo);
  2570. }
  2571. }
  2572. }
  2573. }
  2574. }
  2575. }
  2576. for (i = 0; i < 8; i++) {
  2577. if (lens[i])
  2578. array[i] = i;
  2579. else
  2580. array[i] = -1;
  2581. }
  2582. qsort(array,SIZE(array),sizeof(array[0]),
  2583. (int (*)(const void *,const void *)) verify_sun_cmp);
  2584. if (array[0] == -1) {
  2585. printf(_("No partitions defined\n"));
  2586. return;
  2587. }
  2588. stop = cylinders * heads * sectors;
  2589. if (starts[array[0]])
  2590. printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
  2591. for (i = 0; i < 7 && array[i+1] != -1; i++) {
  2592. printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
  2593. }
  2594. start = starts[array[i]]+lens[array[i]];
  2595. if (start < stop)
  2596. printf(_("Unused gap - sectors %d-%d\n"),start,stop);
  2597. }
  2598. static void
  2599. add_sun_partition(int n, int sys) {
  2600. uint start, stop, stop2;
  2601. uint starts[8], lens[8];
  2602. int whole_disk = 0;
  2603. char mesg[256];
  2604. int i, first, last;
  2605. if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
  2606. printf(_("Partition %d is already defined. Delete "
  2607. "it before re-adding it.\n"), n + 1);
  2608. return;
  2609. }
  2610. fetch_sun(starts,lens,&start,&stop);
  2611. if (stop <= start) {
  2612. if (n == 2)
  2613. whole_disk = 1;
  2614. else {
  2615. printf(_("Other partitions already cover the whole disk.\nDelete "
  2616. "some/shrink them before retry.\n"));
  2617. return;
  2618. }
  2619. }
  2620. snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
  2621. for (;;) {
  2622. if (whole_disk)
  2623. first = read_int(0, 0, 0, 0, mesg);
  2624. else
  2625. first = read_int(scround(start), scround(stop)+1,
  2626. scround(stop), 0, mesg);
  2627. if (display_in_cyl_units)
  2628. first *= units_per_sector;
  2629. else
  2630. /* Starting sector has to be properly aligned */
  2631. first = (first + heads * sectors - 1) / (heads * sectors);
  2632. if (n == 2 && first != 0)
  2633. printf ("\
  2634. It is highly recommended that the third partition covers the whole disk\n\
  2635. and is of type `Whole disk'\n");
  2636. /* ewt asks to add: "don't start a partition at cyl 0"
  2637. However, edmundo@rano.demon.co.uk writes:
  2638. "In addition to having a Sun partition table, to be able to
  2639. boot from the disc, the first partition, /dev/sdX1, must
  2640. start at cylinder 0. This means that /dev/sdX1 contains
  2641. the partition table and the boot block, as these are the
  2642. first two sectors of the disc. Therefore you must be
  2643. careful what you use /dev/sdX1 for. In particular, you must
  2644. not use a partition starting at cylinder 0 for Linux swap,
  2645. as that would overwrite the partition table and the boot
  2646. block. You may, however, use such a partition for a UFS
  2647. or EXT2 file system, as these file systems leave the first
  2648. 1024 bytes undisturbed. */
  2649. /* On the other hand, one should not use partitions
  2650. starting at block 0 in an md, or the label will
  2651. be trashed. */
  2652. for (i = 0; i < partitions; i++)
  2653. if (lens[i] && starts[i] <= first
  2654. && starts[i] + lens[i] > first)
  2655. break;
  2656. if (i < partitions && !whole_disk) {
  2657. if (n == 2 && !first) {
  2658. whole_disk = 1;
  2659. break;
  2660. }
  2661. printf(_("Sector %d is already allocated\n"), first);
  2662. } else
  2663. break;
  2664. }
  2665. stop = cylinders * heads * sectors;
  2666. stop2 = stop;
  2667. for (i = 0; i < partitions; i++) {
  2668. if (starts[i] > first && starts[i] < stop)
  2669. stop = starts[i];
  2670. }
  2671. snprintf(mesg, sizeof(mesg),
  2672. _("Last %s or +size or +sizeM or +sizeK"),
  2673. str_units(SINGULAR));
  2674. if (whole_disk)
  2675. last = read_int(scround(stop2), scround(stop2), scround(stop2),
  2676. 0, mesg);
  2677. else if (n == 2 && !first)
  2678. last = read_int(scround(first), scround(stop2), scround(stop2),
  2679. scround(first), mesg);
  2680. else
  2681. last = read_int(scround(first), scround(stop), scround(stop),
  2682. scround(first), mesg);
  2683. if (display_in_cyl_units)
  2684. last *= units_per_sector;
  2685. if (n == 2 && !first) {
  2686. if (last >= stop2) {
  2687. whole_disk = 1;
  2688. last = stop2;
  2689. } else if (last > stop) {
  2690. printf (
  2691. _("You haven't covered the whole disk with the 3rd partition, but your value\n"
  2692. "%d %s covers some other partition. Your entry has been changed\n"
  2693. "to %d %s\n"),
  2694. scround(last), str_units(SINGULAR),
  2695. scround(stop), str_units(SINGULAR));
  2696. last = stop;
  2697. }
  2698. } else if (!whole_disk && last > stop)
  2699. last = stop;
  2700. if (whole_disk) sys = WHOLE_DISK;
  2701. set_sun_partition(n, first, last, sys);
  2702. }
  2703. static void
  2704. sun_delete_partition(int i) {
  2705. unsigned int nsec;
  2706. if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
  2707. !sunlabel->partitions[i].start_cylinder &&
  2708. (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
  2709. == heads * sectors * cylinders)
  2710. printf(_("If you want to maintain SunOS/Solaris compatibility, "
  2711. "consider leaving this\n"
  2712. "partition as Whole disk (5), starting at 0, with %u "
  2713. "sectors\n"), nsec);
  2714. sunlabel->infos[i].id = 0;
  2715. sunlabel->partitions[i].num_sectors = 0;
  2716. }
  2717. static void
  2718. sun_change_sysid(int i, int sys) {
  2719. if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
  2720. read_chars(
  2721. _("It is highly recommended that the partition at offset 0\n"
  2722. "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
  2723. "there may destroy your partition table and bootblock.\n"
  2724. "Type YES if you're very sure you would like that partition\n"
  2725. "tagged with 82 (Linux swap): "));
  2726. if (strcmp (line_ptr, _("YES\n")))
  2727. return;
  2728. }
  2729. switch (sys) {
  2730. case SUNOS_SWAP:
  2731. case LINUX_SWAP:
  2732. /* swaps are not mountable by default */
  2733. sunlabel->infos[i].flags |= 0x01;
  2734. break;
  2735. default:
  2736. /* assume other types are mountable;
  2737. user can change it anyway */
  2738. sunlabel->infos[i].flags &= ~0x01;
  2739. break;
  2740. }
  2741. sunlabel->infos[i].id = sys;
  2742. }
  2743. static void
  2744. sun_list_table(int xtra) {
  2745. int i, w;
  2746. w = strlen(disk_device);
  2747. if (xtra)
  2748. printf(
  2749. _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
  2750. "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
  2751. "%d extra sects/cyl, interleave %d:1\n"
  2752. "%s\n"
  2753. "Units = %s of %d * 512 bytes\n\n"),
  2754. disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
  2755. cylinders, SUN_SSWAP16(sunlabel->nacyl),
  2756. SUN_SSWAP16(sunlabel->pcylcount),
  2757. SUN_SSWAP16(sunlabel->sparecyl),
  2758. SUN_SSWAP16(sunlabel->ilfact),
  2759. (char *)sunlabel,
  2760. str_units(PLURAL), units_per_sector);
  2761. else
  2762. printf(
  2763. _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
  2764. "Units = %s of %d * 512 bytes\n\n"),
  2765. disk_device, heads, sectors, cylinders,
  2766. str_units(PLURAL), units_per_sector);
  2767. printf(_("%*s Flag Start End Blocks Id System\n"),
  2768. w + 1, _("Device"));
  2769. for (i = 0 ; i < partitions; i++) {
  2770. if (sunlabel->partitions[i].num_sectors) {
  2771. uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
  2772. uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
  2773. printf(
  2774. "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
  2775. /* device */ partname(disk_device, i+1, w),
  2776. /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
  2777. (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
  2778. /* start */ (long) scround(start),
  2779. /* end */ (long) scround(start+len),
  2780. /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
  2781. /* type id */ sunlabel->infos[i].id,
  2782. /* type name */ partition_type(sunlabel->infos[i].id));
  2783. }
  2784. }
  2785. }
  2786. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  2787. static void
  2788. sun_set_alt_cyl(void) {
  2789. sunlabel->nacyl =
  2790. SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
  2791. _("Number of alternate cylinders")));
  2792. }
  2793. static void
  2794. sun_set_ncyl(int cyl) {
  2795. sunlabel->ncyl = SUN_SSWAP16(cyl);
  2796. }
  2797. static void
  2798. sun_set_xcyl(void) {
  2799. sunlabel->sparecyl =
  2800. SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
  2801. _("Extra sectors per cylinder")));
  2802. }
  2803. static void
  2804. sun_set_ilfact(void) {
  2805. sunlabel->ilfact =
  2806. SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
  2807. _("Interleave factor")));
  2808. }
  2809. static void
  2810. sun_set_rspeed(void) {
  2811. sunlabel->rspeed =
  2812. SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
  2813. _("Rotation speed (rpm)")));
  2814. }
  2815. static void
  2816. sun_set_pcylcount(void) {
  2817. sunlabel->pcylcount =
  2818. SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
  2819. _("Number of physical cylinders")));
  2820. }
  2821. #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
  2822. static void
  2823. sun_write_table(void) {
  2824. unsigned short *ush = (unsigned short *)sunlabel;
  2825. unsigned short csum = 0;
  2826. while(ush < (unsigned short *)(&sunlabel->csum))
  2827. csum ^= *ush++;
  2828. sunlabel->csum = csum;
  2829. if (lseek(fd, 0, SEEK_SET) < 0)
  2830. fdisk_fatal(unable_to_seek);
  2831. if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
  2832. fdisk_fatal(unable_to_write);
  2833. }
  2834. #endif /* SUN_LABEL */
  2835. /* DOS partition types */
  2836. static const struct systypes i386_sys_types[] = {
  2837. {"\x00" "Empty"},
  2838. {"\x01" "FAT12"},
  2839. {"\x04" "FAT16 <32M"},
  2840. {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
  2841. {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
  2842. {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
  2843. {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
  2844. {"\x0b" "Win95 FAT32"},
  2845. {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
  2846. {"\x0e" "Win95 FAT16 (LBA)"},
  2847. {"\x0f" "Win95 Ext'd (LBA)"},
  2848. {"\x11" "Hidden FAT12"},
  2849. {"\x12" "Compaq diagnostics"},
  2850. {"\x14" "Hidden FAT16 <32M"},
  2851. {"\x16" "Hidden FAT16"},
  2852. {"\x17" "Hidden HPFS/NTFS"},
  2853. {"\x1b" "Hidden Win95 FAT32"},
  2854. {"\x1c" "Hidden Win95 FAT32 (LBA)"},
  2855. {"\x1e" "Hidden Win95 FAT16 (LBA)"},
  2856. {"\x3c" "PartitionMagic recovery"},
  2857. {"\x41" "PPC PReP Boot"},
  2858. {"\x42" "SFS"},
  2859. {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
  2860. {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
  2861. {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
  2862. {"\x82" "Linux swap"}, /* also Solaris */
  2863. {"\x83" "Linux"},
  2864. {"\x84" "OS/2 hidden C: drive"},
  2865. {"\x85" "Linux extended"},
  2866. {"\x86" "NTFS volume set"},
  2867. {"\x87" "NTFS volume set"},
  2868. {"\x8e" "Linux LVM"},
  2869. {"\x9f" "BSD/OS"}, /* BSDI */
  2870. {"\xa0" "IBM Thinkpad hibernation"},
  2871. {"\xa5" "FreeBSD"}, /* various BSD flavours */
  2872. {"\xa6" "OpenBSD"},
  2873. {"\xa8" "Darwin UFS"},
  2874. {"\xa9" "NetBSD"},
  2875. {"\xab" "Darwin boot"},
  2876. {"\xb7" "BSDI fs"},
  2877. {"\xb8" "BSDI swap"},
  2878. {"\xbe" "Solaris boot"},
  2879. {"\xeb" "BeOS fs"},
  2880. {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
  2881. {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
  2882. {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
  2883. {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
  2884. {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
  2885. autodetect using persistent
  2886. superblock */
  2887. #ifdef CONFIG_WEIRD_PARTITION_TYPES
  2888. {"\x02" "XENIX root"},
  2889. {"\x03" "XENIX usr"},
  2890. {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
  2891. {"\x09" "AIX bootable"}, /* AIX data or Coherent */
  2892. {"\x10" "OPUS"},
  2893. {"\x18" "AST SmartSleep"},
  2894. {"\x24" "NEC DOS"},
  2895. {"\x39" "Plan 9"},
  2896. {"\x40" "Venix 80286"},
  2897. {"\x4d" "QNX4.x"},
  2898. {"\x4e" "QNX4.x 2nd part"},
  2899. {"\x4f" "QNX4.x 3rd part"},
  2900. {"\x50" "OnTrack DM"},
  2901. {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
  2902. {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
  2903. {"\x53" "OnTrack DM6 Aux3"},
  2904. {"\x54" "OnTrackDM6"},
  2905. {"\x55" "EZ-Drive"},
  2906. {"\x56" "Golden Bow"},
  2907. {"\x5c" "Priam Edisk"},
  2908. {"\x61" "SpeedStor"},
  2909. {"\x64" "Novell Netware 286"},
  2910. {"\x65" "Novell Netware 386"},
  2911. {"\x70" "DiskSecure Multi-Boot"},
  2912. {"\x75" "PC/IX"},
  2913. {"\x93" "Amoeba"},
  2914. {"\x94" "Amoeba BBT"}, /* (bad block table) */
  2915. {"\xa7" "NeXTSTEP"},
  2916. {"\xbb" "Boot Wizard hidden"},
  2917. {"\xc1" "DRDOS/sec (FAT-12)"},
  2918. {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
  2919. {"\xc6" "DRDOS/sec (FAT-16)"},
  2920. {"\xc7" "Syrinx"},
  2921. {"\xda" "Non-FS data"},
  2922. {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
  2923. Concurrent DOS or CTOS */
  2924. {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
  2925. {"\xdf" "BootIt"}, /* BootIt EMBRM */
  2926. {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
  2927. extended partition */
  2928. {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
  2929. {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
  2930. partition < 1024 cyl. */
  2931. {"\xf1" "SpeedStor"},
  2932. {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
  2933. {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
  2934. {"\xff" "BBT"}, /* Xenix Bad Block Table */
  2935. #endif
  2936. { 0 }
  2937. };
  2938. /* A valid partition table sector ends in 0x55 0xaa */
  2939. static unsigned int
  2940. part_table_flag(const char *b) {
  2941. return ((uint) b[510]) + (((uint) b[511]) << 8);
  2942. }
  2943. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  2944. static void
  2945. write_part_table_flag(char *b) {
  2946. b[510] = 0x55;
  2947. b[511] = 0xaa;
  2948. }
  2949. /* start_sect and nr_sects are stored little endian on all machines */
  2950. /* moreover, they are not aligned correctly */
  2951. static void
  2952. store4_little_endian(unsigned char *cp, unsigned int val) {
  2953. cp[0] = (val & 0xff);
  2954. cp[1] = ((val >> 8) & 0xff);
  2955. cp[2] = ((val >> 16) & 0xff);
  2956. cp[3] = ((val >> 24) & 0xff);
  2957. }
  2958. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  2959. static unsigned int
  2960. read4_little_endian(const unsigned char *cp) {
  2961. return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
  2962. + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
  2963. }
  2964. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  2965. static void
  2966. set_start_sect(struct partition *p, unsigned int start_sect) {
  2967. store4_little_endian(p->start4, start_sect);
  2968. }
  2969. #endif
  2970. static int32_t
  2971. get_start_sect(const struct partition *p) {
  2972. return read4_little_endian(p->start4);
  2973. }
  2974. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  2975. static void
  2976. set_nr_sects(struct partition *p, int32_t nr_sects) {
  2977. store4_little_endian(p->size4, nr_sects);
  2978. }
  2979. #endif
  2980. static int32_t
  2981. get_nr_sects(const struct partition *p) {
  2982. return read4_little_endian(p->size4);
  2983. }
  2984. /* normally O_RDWR, -l option gives O_RDONLY */
  2985. static int type_open = O_RDWR;
  2986. static int ext_index, /* the prime extended partition */
  2987. listing, /* no aborts for fdisk -l */
  2988. dos_compatible_flag = ~0;
  2989. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  2990. static int dos_changed;
  2991. static int nowarn; /* no warnings for fdisk -l/-s */
  2992. #endif
  2993. static uint user_cylinders, user_heads, user_sectors;
  2994. static uint pt_heads, pt_sectors;
  2995. static uint kern_heads, kern_sectors;
  2996. static off_t extended_offset; /* offset of link pointers */
  2997. static unsigned long long total_number_of_sectors;
  2998. static jmp_buf listingbuf;
  2999. static void fdisk_fatal(enum failure why) {
  3000. const char *message;
  3001. if (listing) {
  3002. close(fd);
  3003. longjmp(listingbuf, 1);
  3004. }
  3005. switch (why) {
  3006. case unable_to_open:
  3007. message = "Unable to open %s\n";
  3008. break;
  3009. case unable_to_read:
  3010. message = "Unable to read %s\n";
  3011. break;
  3012. case unable_to_seek:
  3013. message = "Unable to seek on %s\n";
  3014. break;
  3015. case unable_to_write:
  3016. message = "Unable to write %s\n";
  3017. break;
  3018. case ioctl_error:
  3019. message = "BLKGETSIZE ioctl failed on %s\n";
  3020. break;
  3021. default:
  3022. message = "Fatal error\n";
  3023. }
  3024. fputc('\n', stderr);
  3025. fprintf(stderr, message, disk_device);
  3026. exit(1);
  3027. }
  3028. static void
  3029. seek_sector(off_t secno) {
  3030. off_t offset = secno * sector_size;
  3031. if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
  3032. fdisk_fatal(unable_to_seek);
  3033. }
  3034. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3035. static void
  3036. write_sector(off_t secno, char *buf) {
  3037. seek_sector(secno);
  3038. if (write(fd, buf, sector_size) != sector_size)
  3039. fdisk_fatal(unable_to_write);
  3040. }
  3041. #endif
  3042. /* Allocate a buffer and read a partition table sector */
  3043. static void
  3044. read_pte(struct pte *pe, off_t offset) {
  3045. pe->offset = offset;
  3046. pe->sectorbuffer = (char *) xmalloc(sector_size);
  3047. seek_sector(offset);
  3048. if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
  3049. fdisk_fatal(unable_to_read);
  3050. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3051. pe->changed = 0;
  3052. #endif
  3053. pe->part_table = pe->ext_pointer = NULL;
  3054. }
  3055. static unsigned int
  3056. get_partition_start(const struct pte *pe) {
  3057. return pe->offset + get_start_sect(pe->part_table);
  3058. }
  3059. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3060. /*
  3061. * Avoid warning about DOS partitions when no DOS partition was changed.
  3062. * Here a heuristic "is probably dos partition".
  3063. * We might also do the opposite and warn in all cases except
  3064. * for "is probably nondos partition".
  3065. */
  3066. static int
  3067. is_dos_partition(int t) {
  3068. return (t == 1 || t == 4 || t == 6 ||
  3069. t == 0x0b || t == 0x0c || t == 0x0e ||
  3070. t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
  3071. t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
  3072. t == 0xc1 || t == 0xc4 || t == 0xc6);
  3073. }
  3074. static void
  3075. menu(void) {
  3076. #ifdef CONFIG_FEATURE_SUN_LABEL
  3077. if (sun_label) {
  3078. puts(_("Command action"));
  3079. puts(_("\ta\ttoggle a read only flag")); /* sun */
  3080. puts(_("\tb\tedit bsd disklabel"));
  3081. puts(_("\tc\ttoggle the mountable flag")); /* sun */
  3082. puts(_("\td\tdelete a partition"));
  3083. puts(_("\tl\tlist known partition types"));
  3084. puts(_("\tm\tprint this menu"));
  3085. puts(_("\tn\tadd a new partition"));
  3086. puts(_("\to\tcreate a new empty DOS partition table"));
  3087. puts(_("\tp\tprint the partition table"));
  3088. puts(_("\tq\tquit without saving changes"));
  3089. puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
  3090. puts(_("\tt\tchange a partition's system id"));
  3091. puts(_("\tu\tchange display/entry units"));
  3092. puts(_("\tv\tverify the partition table"));
  3093. puts(_("\tw\twrite table to disk and exit"));
  3094. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  3095. puts(_("\tx\textra functionality (experts only)"));
  3096. #endif
  3097. } else
  3098. #endif
  3099. #ifdef CONFIG_FEATURE_SGI_LABEL
  3100. if (sgi_label) {
  3101. puts(_("Command action"));
  3102. puts(_("\ta\tselect bootable partition")); /* sgi flavour */
  3103. puts(_("\tb\tedit bootfile entry")); /* sgi */
  3104. puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
  3105. puts(_("\td\tdelete a partition"));
  3106. puts(_("\tl\tlist known partition types"));
  3107. puts(_("\tm\tprint this menu"));
  3108. puts(_("\tn\tadd a new partition"));
  3109. puts(_("\to\tcreate a new empty DOS partition table"));
  3110. puts(_("\tp\tprint the partition table"));
  3111. puts(_("\tq\tquit without saving changes"));
  3112. puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
  3113. puts(_("\tt\tchange a partition's system id"));
  3114. puts(_("\tu\tchange display/entry units"));
  3115. puts(_("\tv\tverify the partition table"));
  3116. puts(_("\tw\twrite table to disk and exit"));
  3117. } else
  3118. #endif
  3119. #ifdef CONFIG_FEATURE_AIX_LABEL
  3120. if (aix_label) {
  3121. puts(_("Command action"));
  3122. puts(_("\tm\tprint this menu"));
  3123. puts(_("\to\tcreate a new empty DOS partition table"));
  3124. puts(_("\tq\tquit without saving changes"));
  3125. puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
  3126. } else
  3127. #endif
  3128. {
  3129. puts(_("Command action"));
  3130. puts(_("\ta\ttoggle a bootable flag"));
  3131. puts(_("\tb\tedit bsd disklabel"));
  3132. puts(_("\tc\ttoggle the dos compatibility flag"));
  3133. puts(_("\td\tdelete a partition"));
  3134. puts(_("\tl\tlist known partition types"));
  3135. puts(_("\tm\tprint this menu"));
  3136. puts(_("\tn\tadd a new partition"));
  3137. puts(_("\to\tcreate a new empty DOS partition table"));
  3138. puts(_("\tp\tprint the partition table"));
  3139. puts(_("\tq\tquit without saving changes"));
  3140. puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
  3141. puts(_("\tt\tchange a partition's system id"));
  3142. puts(_("\tu\tchange display/entry units"));
  3143. puts(_("\tv\tverify the partition table"));
  3144. puts(_("\tw\twrite table to disk and exit"));
  3145. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  3146. puts(_("\tx\textra functionality (experts only)"));
  3147. #endif
  3148. }
  3149. }
  3150. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  3151. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  3152. static void
  3153. xmenu(void) {
  3154. #ifdef CONFIG_FEATURE_SUN_LABEL
  3155. if (sun_label) {
  3156. puts(_("Command action"));
  3157. puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
  3158. puts(_("\tc\tchange number of cylinders"));
  3159. puts(_("\td\tprint the raw data in the partition table"));
  3160. puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
  3161. puts(_("\th\tchange number of heads"));
  3162. puts(_("\ti\tchange interleave factor")); /*sun*/
  3163. puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
  3164. puts(_("\tm\tprint this menu"));
  3165. puts(_("\tp\tprint the partition table"));
  3166. puts(_("\tq\tquit without saving changes"));
  3167. puts(_("\tr\treturn to main menu"));
  3168. puts(_("\ts\tchange number of sectors/track"));
  3169. puts(_("\tv\tverify the partition table"));
  3170. puts(_("\tw\twrite table to disk and exit"));
  3171. puts(_("\ty\tchange number of physical cylinders")); /*sun*/
  3172. } else
  3173. #endif
  3174. #ifdef CONFIG_FEATURE_SGI_LABEL
  3175. if (sgi_label) {
  3176. puts(_("Command action"));
  3177. puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
  3178. puts(_("\tc\tchange number of cylinders"));
  3179. puts(_("\td\tprint the raw data in the partition table"));
  3180. puts(_("\te\tlist extended partitions")); /* !sun */
  3181. puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
  3182. puts(_("\th\tchange number of heads"));
  3183. puts(_("\tm\tprint this menu"));
  3184. puts(_("\tp\tprint the partition table"));
  3185. puts(_("\tq\tquit without saving changes"));
  3186. puts(_("\tr\treturn to main menu"));
  3187. puts(_("\ts\tchange number of sectors/track"));
  3188. puts(_("\tv\tverify the partition table"));
  3189. puts(_("\tw\twrite table to disk and exit"));
  3190. } else
  3191. #endif
  3192. #ifdef CONFIG_FEATURE_AIX_LABEL
  3193. if (aix_label) {
  3194. puts(_("Command action"));
  3195. puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
  3196. puts(_("\tc\tchange number of cylinders"));
  3197. puts(_("\td\tprint the raw data in the partition table"));
  3198. puts(_("\te\tlist extended partitions")); /* !sun */
  3199. puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
  3200. puts(_("\th\tchange number of heads"));
  3201. puts(_("\tm\tprint this menu"));
  3202. puts(_("\tp\tprint the partition table"));
  3203. puts(_("\tq\tquit without saving changes"));
  3204. puts(_("\tr\treturn to main menu"));
  3205. puts(_("\ts\tchange number of sectors/track"));
  3206. puts(_("\tv\tverify the partition table"));
  3207. puts(_("\tw\twrite table to disk and exit"));
  3208. } else
  3209. #endif
  3210. {
  3211. puts(_("Command action"));
  3212. puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
  3213. puts(_("\tc\tchange number of cylinders"));
  3214. puts(_("\td\tprint the raw data in the partition table"));
  3215. puts(_("\te\tlist extended partitions")); /* !sun */
  3216. puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
  3217. #ifdef CONFIG_FEATURE_SGI_LABEL
  3218. puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
  3219. #endif
  3220. puts(_("\th\tchange number of heads"));
  3221. puts(_("\tm\tprint this menu"));
  3222. puts(_("\tp\tprint the partition table"));
  3223. puts(_("\tq\tquit without saving changes"));
  3224. puts(_("\tr\treturn to main menu"));
  3225. puts(_("\ts\tchange number of sectors/track"));
  3226. puts(_("\tv\tverify the partition table"));
  3227. puts(_("\tw\twrite table to disk and exit"));
  3228. }
  3229. }
  3230. #endif /* ADVANCED mode */
  3231. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3232. static const struct systypes *
  3233. get_sys_types(void) {
  3234. return (
  3235. #ifdef CONFIG_FEATURE_SUN_LABEL
  3236. sun_label ? sun_sys_types :
  3237. #endif
  3238. #ifdef CONFIG_FEATURE_SGI_LABEL
  3239. sgi_label ? sgi_sys_types :
  3240. #endif
  3241. i386_sys_types);
  3242. }
  3243. #else
  3244. #define get_sys_types() i386_sys_types
  3245. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  3246. static const char *partition_type(unsigned char type)
  3247. {
  3248. int i;
  3249. const struct systypes *types = get_sys_types();
  3250. for (i=0; types[i].name; i++)
  3251. if (types[i].name[0] == type)
  3252. return types[i].name + 1;
  3253. return _("Unknown");
  3254. }
  3255. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3256. static int
  3257. get_sysid(int i) {
  3258. return (
  3259. #ifdef CONFIG_FEATURE_SUN_LABEL
  3260. sun_label ? sunlabel->infos[i].id :
  3261. #endif
  3262. #ifdef CONFIG_FEATURE_SGI_LABEL
  3263. sgi_label ? sgi_get_sysid(i) :
  3264. #endif
  3265. ptes[i].part_table->sys_ind);
  3266. }
  3267. void list_types(const struct systypes *sys)
  3268. {
  3269. uint last[4], done = 0, next = 0, size;
  3270. int i;
  3271. for (i = 0; sys[i].name; i++);
  3272. size = i;
  3273. for (i = 3; i >= 0; i--)
  3274. last[3 - i] = done += (size + i - done) / (i + 1);
  3275. i = done = 0;
  3276. do {
  3277. printf("%c%2x %-15.15s", i ? ' ' : '\n',
  3278. sys[next].name[0], partition_type(sys[next].name[0]));
  3279. next = last[i++] + done;
  3280. if (i > 3 || next >= last[i]) {
  3281. i = 0;
  3282. next = ++done;
  3283. }
  3284. } while (done < last[0]);
  3285. putchar('\n');
  3286. }
  3287. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  3288. static int
  3289. is_cleared_partition(const struct partition *p) {
  3290. return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
  3291. p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
  3292. get_start_sect(p) || get_nr_sects(p));
  3293. }
  3294. static void
  3295. clear_partition(struct partition *p) {
  3296. if (!p)
  3297. return;
  3298. memset(p, 0, sizeof(struct partition));
  3299. }
  3300. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3301. static void
  3302. set_partition(int i, int doext, off_t start, off_t stop, int sysid) {
  3303. struct partition *p;
  3304. off_t offset;
  3305. if (doext) {
  3306. p = ptes[i].ext_pointer;
  3307. offset = extended_offset;
  3308. } else {
  3309. p = ptes[i].part_table;
  3310. offset = ptes[i].offset;
  3311. }
  3312. p->boot_ind = 0;
  3313. p->sys_ind = sysid;
  3314. set_start_sect(p, start - offset);
  3315. set_nr_sects(p, stop - start + 1);
  3316. if (dos_compatible_flag && (start/(sectors*heads) > 1023))
  3317. start = heads*sectors*1024 - 1;
  3318. set_hsc(p->head, p->sector, p->cyl, start);
  3319. if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
  3320. stop = heads*sectors*1024 - 1;
  3321. set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
  3322. ptes[i].changed = 1;
  3323. }
  3324. #endif
  3325. static int
  3326. test_c(const char **m, const char *mesg) {
  3327. int val = 0;
  3328. if (!*m)
  3329. fprintf(stderr, _("You must set"));
  3330. else {
  3331. fprintf(stderr, " %s", *m);
  3332. val = 1;
  3333. }
  3334. *m = mesg;
  3335. return val;
  3336. }
  3337. static int
  3338. warn_geometry(void) {
  3339. const char *m = NULL;
  3340. int prev = 0;
  3341. if (!heads)
  3342. prev = test_c(&m, _("heads"));
  3343. if (!sectors)
  3344. prev = test_c(&m, _("sectors"));
  3345. if (!cylinders)
  3346. prev = test_c(&m, _("cylinders"));
  3347. if (!m)
  3348. return 0;
  3349. fprintf(stderr, "%s%s.\n"
  3350. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3351. "You can do this from the extra functions menu.\n"
  3352. #endif
  3353. , prev ? _(" and ") : " ", m);
  3354. return 1;
  3355. }
  3356. static void update_units(void)
  3357. {
  3358. int cyl_units = heads * sectors;
  3359. if (display_in_cyl_units && cyl_units)
  3360. units_per_sector = cyl_units;
  3361. else
  3362. units_per_sector = 1; /* in sectors */
  3363. }
  3364. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3365. static void
  3366. warn_cylinders(void) {
  3367. if (dos_label && cylinders > 1024 && !nowarn)
  3368. fprintf(stderr, _("\n"
  3369. "The number of cylinders for this disk is set to %d.\n"
  3370. "There is nothing wrong with that, but this is larger than 1024,\n"
  3371. "and could in certain setups cause problems with:\n"
  3372. "1) software that runs at boot time (e.g., old versions of LILO)\n"
  3373. "2) booting and partitioning software from other OSs\n"
  3374. " (e.g., DOS FDISK, OS/2 FDISK)\n"),
  3375. cylinders);
  3376. }
  3377. #endif
  3378. static void
  3379. read_extended(int ext) {
  3380. int i;
  3381. struct pte *pex;
  3382. struct partition *p, *q;
  3383. ext_index = ext;
  3384. pex = &ptes[ext];
  3385. pex->ext_pointer = pex->part_table;
  3386. p = pex->part_table;
  3387. if (!get_start_sect(p)) {
  3388. fprintf(stderr,
  3389. _("Bad offset in primary extended partition\n"));
  3390. return;
  3391. }
  3392. while (IS_EXTENDED (p->sys_ind)) {
  3393. struct pte *pe = &ptes[partitions];
  3394. if (partitions >= MAXIMUM_PARTS) {
  3395. /* This is not a Linux restriction, but
  3396. this program uses arrays of size MAXIMUM_PARTS.
  3397. Do not try to `improve' this test. */
  3398. struct pte *pre = &ptes[partitions-1];
  3399. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3400. fprintf(stderr,
  3401. _("Warning: deleting partitions after %d\n"),
  3402. partitions);
  3403. pre->changed = 1;
  3404. #endif
  3405. clear_partition(pre->ext_pointer);
  3406. return;
  3407. }
  3408. read_pte(pe, extended_offset + get_start_sect(p));
  3409. if (!extended_offset)
  3410. extended_offset = get_start_sect(p);
  3411. q = p = pt_offset(pe->sectorbuffer, 0);
  3412. for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
  3413. if (IS_EXTENDED (p->sys_ind)) {
  3414. if (pe->ext_pointer)
  3415. fprintf(stderr,
  3416. _("Warning: extra link "
  3417. "pointer in partition table"
  3418. " %d\n"), partitions + 1);
  3419. else
  3420. pe->ext_pointer = p;
  3421. } else if (p->sys_ind) {
  3422. if (pe->part_table)
  3423. fprintf(stderr,
  3424. _("Warning: ignoring extra "
  3425. "data in partition table"
  3426. " %d\n"), partitions + 1);
  3427. else
  3428. pe->part_table = p;
  3429. }
  3430. }
  3431. /* very strange code here... */
  3432. if (!pe->part_table) {
  3433. if (q != pe->ext_pointer)
  3434. pe->part_table = q;
  3435. else
  3436. pe->part_table = q + 1;
  3437. }
  3438. if (!pe->ext_pointer) {
  3439. if (q != pe->part_table)
  3440. pe->ext_pointer = q;
  3441. else
  3442. pe->ext_pointer = q + 1;
  3443. }
  3444. p = pe->ext_pointer;
  3445. partitions++;
  3446. }
  3447. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3448. /* remove empty links */
  3449. remove:
  3450. for (i = 4; i < partitions; i++) {
  3451. struct pte *pe = &ptes[i];
  3452. if (!get_nr_sects(pe->part_table) &&
  3453. (partitions > 5 || ptes[4].part_table->sys_ind)) {
  3454. printf("omitting empty partition (%d)\n", i+1);
  3455. delete_partition(i);
  3456. goto remove; /* numbering changed */
  3457. }
  3458. }
  3459. #endif
  3460. }
  3461. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3462. static void
  3463. create_doslabel(void) {
  3464. int i;
  3465. fprintf(stderr,
  3466. _("Building a new DOS disklabel. Changes will remain in memory only,\n"
  3467. "until you decide to write them. After that, of course, the previous\n"
  3468. "content won't be recoverable.\n\n"));
  3469. #ifdef CONFIG_FEATURE_SUN_LABEL
  3470. sun_nolabel(); /* otherwise always recognised as sun */
  3471. #endif
  3472. #ifdef CONFIG_FEATURE_SGI_LABEL
  3473. sgi_nolabel(); /* otherwise always recognised as sgi */
  3474. #endif
  3475. #ifdef CONFIG_FEATURE_AIX_LABEL
  3476. aix_label = 0;
  3477. #endif
  3478. #ifdef CONFIG_FEATURE_OSF_LABEL
  3479. osf_label = 0;
  3480. possibly_osf_label = 0;
  3481. #endif
  3482. partitions = 4;
  3483. for (i = 510-64; i < 510; i++)
  3484. MBRbuffer[i] = 0;
  3485. write_part_table_flag(MBRbuffer);
  3486. extended_offset = 0;
  3487. set_all_unchanged();
  3488. set_changed(0);
  3489. get_boot(create_empty_dos);
  3490. }
  3491. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  3492. static void
  3493. get_sectorsize(void) {
  3494. if (!user_set_sector_size &&
  3495. get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
  3496. int arg;
  3497. if (ioctl(fd, BLKSSZGET, &arg) == 0)
  3498. sector_size = arg;
  3499. if (sector_size != DEFAULT_SECTOR_SIZE)
  3500. printf(_("Note: sector size is %d (not %d)\n"),
  3501. sector_size, DEFAULT_SECTOR_SIZE);
  3502. }
  3503. }
  3504. static inline void
  3505. get_kernel_geometry(void) {
  3506. struct hd_geometry geometry;
  3507. if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
  3508. kern_heads = geometry.heads;
  3509. kern_sectors = geometry.sectors;
  3510. /* never use geometry.cylinders - it is truncated */
  3511. }
  3512. }
  3513. static void
  3514. get_partition_table_geometry(void) {
  3515. const unsigned char *bufp = MBRbuffer;
  3516. struct partition *p;
  3517. int i, h, s, hh, ss;
  3518. int first = 1;
  3519. int bad = 0;
  3520. if (!(valid_part_table_flag(bufp)))
  3521. return;
  3522. hh = ss = 0;
  3523. for (i=0; i<4; i++) {
  3524. p = pt_offset(bufp, i);
  3525. if (p->sys_ind != 0) {
  3526. h = p->end_head + 1;
  3527. s = (p->end_sector & 077);
  3528. if (first) {
  3529. hh = h;
  3530. ss = s;
  3531. first = 0;
  3532. } else if (hh != h || ss != s)
  3533. bad = 1;
  3534. }
  3535. }
  3536. if (!first && !bad) {
  3537. pt_heads = hh;
  3538. pt_sectors = ss;
  3539. }
  3540. }
  3541. void
  3542. get_geometry(void) {
  3543. int sec_fac;
  3544. unsigned long long bytes; /* really u64 */
  3545. get_sectorsize();
  3546. sec_fac = sector_size / 512;
  3547. #ifdef CONFIG_FEATURE_SUN_LABEL
  3548. guess_device_type();
  3549. #endif
  3550. heads = cylinders = sectors = 0;
  3551. kern_heads = kern_sectors = 0;
  3552. pt_heads = pt_sectors = 0;
  3553. get_kernel_geometry();
  3554. get_partition_table_geometry();
  3555. heads = user_heads ? user_heads :
  3556. pt_heads ? pt_heads :
  3557. kern_heads ? kern_heads : 255;
  3558. sectors = user_sectors ? user_sectors :
  3559. pt_sectors ? pt_sectors :
  3560. kern_sectors ? kern_sectors : 63;
  3561. if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
  3562. /* got bytes */
  3563. } else {
  3564. unsigned long longsectors;
  3565. if (ioctl(fd, BLKGETSIZE, &longsectors))
  3566. longsectors = 0;
  3567. bytes = ((unsigned long long) longsectors) << 9;
  3568. }
  3569. total_number_of_sectors = (bytes >> 9);
  3570. sector_offset = 1;
  3571. if (dos_compatible_flag)
  3572. sector_offset = sectors;
  3573. cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
  3574. if (!cylinders)
  3575. cylinders = user_cylinders;
  3576. }
  3577. /*
  3578. * Read MBR. Returns:
  3579. * -1: no 0xaa55 flag present (possibly entire disk BSD)
  3580. * 0: found or created label
  3581. * 1: I/O error
  3582. */
  3583. int
  3584. get_boot(enum action what) {
  3585. int i;
  3586. partitions = 4;
  3587. for (i = 0; i < 4; i++) {
  3588. struct pte *pe = &ptes[i];
  3589. pe->part_table = pt_offset(MBRbuffer, i);
  3590. pe->ext_pointer = NULL;
  3591. pe->offset = 0;
  3592. pe->sectorbuffer = MBRbuffer;
  3593. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3594. pe->changed = (what == create_empty_dos);
  3595. #endif
  3596. }
  3597. #ifdef CONFIG_FEATURE_SUN_LABEL
  3598. if (what == create_empty_sun && check_sun_label())
  3599. return 0;
  3600. #endif
  3601. memset(MBRbuffer, 0, 512);
  3602. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3603. if (what == create_empty_dos)
  3604. goto got_dos_table; /* skip reading disk */
  3605. if ((fd = open(disk_device, type_open)) < 0) {
  3606. if ((fd = open(disk_device, O_RDONLY)) < 0) {
  3607. if (what == try_only)
  3608. return 1;
  3609. fdisk_fatal(unable_to_open);
  3610. } else
  3611. printf(_("You will not be able to write "
  3612. "the partition table.\n"));
  3613. }
  3614. if (512 != read(fd, MBRbuffer, 512)) {
  3615. if (what == try_only)
  3616. return 1;
  3617. fdisk_fatal(unable_to_read);
  3618. }
  3619. #else
  3620. if ((fd = open(disk_device, O_RDONLY)) < 0)
  3621. return 1;
  3622. if (512 != read(fd, MBRbuffer, 512))
  3623. return 1;
  3624. #endif
  3625. get_geometry();
  3626. update_units();
  3627. #ifdef CONFIG_FEATURE_SUN_LABEL
  3628. if (check_sun_label())
  3629. return 0;
  3630. #endif
  3631. #ifdef CONFIG_FEATURE_SGI_LABEL
  3632. if (check_sgi_label())
  3633. return 0;
  3634. #endif
  3635. #ifdef CONFIG_FEATURE_AIX_LABEL
  3636. if (check_aix_label())
  3637. return 0;
  3638. #endif
  3639. #ifdef CONFIG_FEATURE_OSF_LABEL
  3640. if (check_osf_label()) {
  3641. possibly_osf_label = 1;
  3642. if (!valid_part_table_flag(MBRbuffer)) {
  3643. osf_label = 1;
  3644. return 0;
  3645. }
  3646. printf(_("This disk has both DOS and BSD magic.\n"
  3647. "Give the 'b' command to go to BSD mode.\n"));
  3648. }
  3649. #endif
  3650. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3651. got_dos_table:
  3652. #endif
  3653. if (!valid_part_table_flag(MBRbuffer)) {
  3654. #ifndef CONFIG_FEATURE_FDISK_WRITABLE
  3655. return -1;
  3656. #else
  3657. switch(what) {
  3658. case fdisk:
  3659. fprintf(stderr,
  3660. _("Device contains neither a valid DOS "
  3661. "partition table, nor Sun, SGI or OSF "
  3662. "disklabel\n"));
  3663. #ifdef __sparc__
  3664. #ifdef CONFIG_FEATURE_SUN_LABEL
  3665. create_sunlabel();
  3666. #endif
  3667. #else
  3668. create_doslabel();
  3669. #endif
  3670. return 0;
  3671. case try_only:
  3672. return -1;
  3673. case create_empty_dos:
  3674. #ifdef CONFIG_FEATURE_SUN_LABEL
  3675. case create_empty_sun:
  3676. #endif
  3677. break;
  3678. default:
  3679. fprintf(stderr, _("Internal error\n"));
  3680. exit(1);
  3681. }
  3682. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  3683. }
  3684. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3685. warn_cylinders();
  3686. #endif
  3687. warn_geometry();
  3688. for (i = 0; i < 4; i++) {
  3689. struct pte *pe = &ptes[i];
  3690. if (IS_EXTENDED (pe->part_table->sys_ind)) {
  3691. if (partitions != 4)
  3692. fprintf(stderr, _("Ignoring extra extended "
  3693. "partition %d\n"), i + 1);
  3694. else
  3695. read_extended(i);
  3696. }
  3697. }
  3698. for (i = 3; i < partitions; i++) {
  3699. struct pte *pe = &ptes[i];
  3700. if (!valid_part_table_flag(pe->sectorbuffer)) {
  3701. fprintf(stderr,
  3702. _("Warning: invalid flag 0x%04x of partition "
  3703. "table %d will be corrected by w(rite)\n"),
  3704. part_table_flag(pe->sectorbuffer), i + 1);
  3705. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3706. pe->changed = 1;
  3707. #endif
  3708. }
  3709. }
  3710. return 0;
  3711. }
  3712. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  3713. /*
  3714. * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
  3715. * If the user hits Enter, DFLT is returned.
  3716. * Answers like +10 are interpreted as offsets from BASE.
  3717. *
  3718. * There is no default if DFLT is not between LOW and HIGH.
  3719. */
  3720. static uint
  3721. read_int(uint low, uint dflt, uint high, uint base, char *mesg)
  3722. {
  3723. uint i;
  3724. int default_ok = 1;
  3725. static char *ms = NULL;
  3726. static int mslen = 0;
  3727. if (!ms || strlen(mesg)+100 > mslen) {
  3728. mslen = strlen(mesg)+200;
  3729. ms = xrealloc(ms,mslen);
  3730. }
  3731. if (dflt < low || dflt > high)
  3732. default_ok = 0;
  3733. if (default_ok)
  3734. snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
  3735. mesg, low, high, dflt);
  3736. else
  3737. snprintf(ms, mslen, "%s (%u-%u): ",
  3738. mesg, low, high);
  3739. while (1) {
  3740. int use_default = default_ok;
  3741. /* ask question and read answer */
  3742. while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
  3743. && *line_ptr != '-' && *line_ptr != '+')
  3744. continue;
  3745. if (*line_ptr == '+' || *line_ptr == '-') {
  3746. int minus = (*line_ptr == '-');
  3747. int absolute = 0;
  3748. i = atoi(line_ptr+1);
  3749. while (isdigit(*++line_ptr))
  3750. use_default = 0;
  3751. switch (*line_ptr) {
  3752. case 'c':
  3753. case 'C':
  3754. if (!display_in_cyl_units)
  3755. i *= heads * sectors;
  3756. break;
  3757. case 'K':
  3758. absolute = 1024;
  3759. break;
  3760. case 'k':
  3761. absolute = 1000;
  3762. break;
  3763. case 'm':
  3764. case 'M':
  3765. absolute = 1000000;
  3766. break;
  3767. case 'g':
  3768. case 'G':
  3769. absolute = 1000000000;
  3770. break;
  3771. default:
  3772. break;
  3773. }
  3774. if (absolute) {
  3775. unsigned long long bytes;
  3776. unsigned long unit;
  3777. bytes = (unsigned long long) i * absolute;
  3778. unit = sector_size * units_per_sector;
  3779. bytes += unit/2; /* round */
  3780. bytes /= unit;
  3781. i = bytes;
  3782. }
  3783. if (minus)
  3784. i = -i;
  3785. i += base;
  3786. } else {
  3787. i = atoi(line_ptr);
  3788. while (isdigit(*line_ptr)) {
  3789. line_ptr++;
  3790. use_default = 0;
  3791. }
  3792. }
  3793. if (use_default)
  3794. printf(_("Using default value %u\n"), i = dflt);
  3795. if (i >= low && i <= high)
  3796. break;
  3797. else
  3798. printf(_("Value out of range.\n"));
  3799. }
  3800. return i;
  3801. }
  3802. int
  3803. get_partition(int warn, int max) {
  3804. struct pte *pe;
  3805. int i;
  3806. i = read_int(1, 0, max, 0, _("Partition number")) - 1;
  3807. pe = &ptes[i];
  3808. if (warn) {
  3809. if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
  3810. #ifdef CONFIG_FEATURE_SUN_LABEL
  3811. || (sun_label &&
  3812. (!sunlabel->partitions[i].num_sectors ||
  3813. !sunlabel->infos[i].id))
  3814. #endif
  3815. #ifdef CONFIG_FEATURE_SGI_LABEL
  3816. || (sgi_label && (!sgi_get_num_sectors(i)))
  3817. #endif
  3818. )
  3819. fprintf(stderr,
  3820. _("Warning: partition %d has empty type\n"),
  3821. i+1);
  3822. }
  3823. return i;
  3824. }
  3825. static int
  3826. get_existing_partition(int warn, int max) {
  3827. int pno = -1;
  3828. int i;
  3829. for (i = 0; i < max; i++) {
  3830. struct pte *pe = &ptes[i];
  3831. struct partition *p = pe->part_table;
  3832. if (p && !is_cleared_partition(p)) {
  3833. if (pno >= 0)
  3834. goto not_unique;
  3835. pno = i;
  3836. }
  3837. }
  3838. if (pno >= 0) {
  3839. printf(_("Selected partition %d\n"), pno+1);
  3840. return pno;
  3841. }
  3842. printf(_("No partition is defined yet!\n"));
  3843. return -1;
  3844. not_unique:
  3845. return get_partition(warn, max);
  3846. }
  3847. static int
  3848. get_nonexisting_partition(int warn, int max) {
  3849. int pno = -1;
  3850. int i;
  3851. for (i = 0; i < max; i++) {
  3852. struct pte *pe = &ptes[i];
  3853. struct partition *p = pe->part_table;
  3854. if (p && is_cleared_partition(p)) {
  3855. if (pno >= 0)
  3856. goto not_unique;
  3857. pno = i;
  3858. }
  3859. }
  3860. if (pno >= 0) {
  3861. printf(_("Selected partition %d\n"), pno+1);
  3862. return pno;
  3863. }
  3864. printf(_("All primary partitions have been defined already!\n"));
  3865. return -1;
  3866. not_unique:
  3867. return get_partition(warn, max);
  3868. }
  3869. void change_units(void)
  3870. {
  3871. display_in_cyl_units = !display_in_cyl_units;
  3872. update_units();
  3873. printf(_("Changing display/entry units to %s\n"),
  3874. str_units(PLURAL));
  3875. }
  3876. static void
  3877. toggle_active(int i) {
  3878. struct pte *pe = &ptes[i];
  3879. struct partition *p = pe->part_table;
  3880. if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
  3881. fprintf(stderr,
  3882. _("WARNING: Partition %d is an extended partition\n"),
  3883. i + 1);
  3884. p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
  3885. pe->changed = 1;
  3886. }
  3887. static void
  3888. toggle_dos_compatibility_flag(void) {
  3889. dos_compatible_flag = ~dos_compatible_flag;
  3890. if (dos_compatible_flag) {
  3891. sector_offset = sectors;
  3892. printf(_("DOS Compatibility flag is set\n"));
  3893. }
  3894. else {
  3895. sector_offset = 1;
  3896. printf(_("DOS Compatibility flag is not set\n"));
  3897. }
  3898. }
  3899. static void
  3900. delete_partition(int i) {
  3901. struct pte *pe = &ptes[i];
  3902. struct partition *p = pe->part_table;
  3903. struct partition *q = pe->ext_pointer;
  3904. /* Note that for the fifth partition (i == 4) we don't actually
  3905. * decrement partitions.
  3906. */
  3907. if (warn_geometry())
  3908. return; /* C/H/S not set */
  3909. pe->changed = 1;
  3910. #ifdef CONFIG_FEATURE_SUN_LABEL
  3911. if (sun_label) {
  3912. sun_delete_partition(i);
  3913. return;
  3914. }
  3915. #endif
  3916. #ifdef CONFIG_FEATURE_SGI_LABEL
  3917. if (sgi_label) {
  3918. sgi_delete_partition(i);
  3919. return;
  3920. }
  3921. #endif
  3922. if (i < 4) {
  3923. if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
  3924. partitions = 4;
  3925. ptes[ext_index].ext_pointer = NULL;
  3926. extended_offset = 0;
  3927. }
  3928. clear_partition(p);
  3929. return;
  3930. }
  3931. if (!q->sys_ind && i > 4) {
  3932. /* the last one in the chain - just delete */
  3933. --partitions;
  3934. --i;
  3935. clear_partition(ptes[i].ext_pointer);
  3936. ptes[i].changed = 1;
  3937. } else {
  3938. /* not the last one - further ones will be moved down */
  3939. if (i > 4) {
  3940. /* delete this link in the chain */
  3941. p = ptes[i-1].ext_pointer;
  3942. *p = *q;
  3943. set_start_sect(p, get_start_sect(q));
  3944. set_nr_sects(p, get_nr_sects(q));
  3945. ptes[i-1].changed = 1;
  3946. } else if (partitions > 5) { /* 5 will be moved to 4 */
  3947. /* the first logical in a longer chain */
  3948. pe = &ptes[5];
  3949. if (pe->part_table) /* prevent SEGFAULT */
  3950. set_start_sect(pe->part_table,
  3951. get_partition_start(pe) -
  3952. extended_offset);
  3953. pe->offset = extended_offset;
  3954. pe->changed = 1;
  3955. }
  3956. if (partitions > 5) {
  3957. partitions--;
  3958. while (i < partitions) {
  3959. ptes[i] = ptes[i+1];
  3960. i++;
  3961. }
  3962. } else
  3963. /* the only logical: clear only */
  3964. clear_partition(ptes[i].part_table);
  3965. }
  3966. }
  3967. static void
  3968. change_sysid(void) {
  3969. int i, sys, origsys;
  3970. struct partition *p;
  3971. #ifdef CONFIG_FEATURE_SGI_LABEL
  3972. /* If sgi_label then don't use get_existing_partition,
  3973. let the user select a partition, since get_existing_partition()
  3974. only works for Linux like partition tables. */
  3975. if (!sgi_label) {
  3976. i = get_existing_partition(0, partitions);
  3977. } else {
  3978. i = get_partition(0, partitions);
  3979. }
  3980. #else
  3981. i = get_existing_partition(0, partitions);
  3982. #endif
  3983. if (i == -1)
  3984. return;
  3985. p = ptes[i].part_table;
  3986. origsys = sys = get_sysid(i);
  3987. /* if changing types T to 0 is allowed, then
  3988. the reverse change must be allowed, too */
  3989. if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
  3990. printf(_("Partition %d does not exist yet!\n"), i + 1);
  3991. else while (1) {
  3992. sys = read_hex (get_sys_types());
  3993. if (!sys && !sgi_label && !sun_label) {
  3994. printf(_("Type 0 means free space to many systems\n"
  3995. "(but not to Linux). Having partitions of\n"
  3996. "type 0 is probably unwise. You can delete\n"
  3997. "a partition using the `d' command.\n"));
  3998. /* break; */
  3999. }
  4000. if (!sun_label && !sgi_label) {
  4001. if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
  4002. printf(_("You cannot change a partition into"
  4003. " an extended one or vice versa\n"
  4004. "Delete it first.\n"));
  4005. break;
  4006. }
  4007. }
  4008. if (sys < 256) {
  4009. #ifdef CONFIG_FEATURE_SUN_LABEL
  4010. if (sun_label && i == 2 && sys != WHOLE_DISK)
  4011. printf(_("Consider leaving partition 3 "
  4012. "as Whole disk (5),\n"
  4013. "as SunOS/Solaris expects it and "
  4014. "even Linux likes it.\n\n"));
  4015. #endif
  4016. #ifdef CONFIG_FEATURE_SGI_LABEL
  4017. if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
  4018. || (i == 8 && sys != 0)))
  4019. printf(_("Consider leaving partition 9 "
  4020. "as volume header (0),\nand "
  4021. "partition 11 as entire volume (6)"
  4022. "as IRIX expects it.\n\n"));
  4023. #endif
  4024. if (sys == origsys)
  4025. break;
  4026. #ifdef CONFIG_FEATURE_SUN_LABEL
  4027. if (sun_label) {
  4028. sun_change_sysid(i, sys);
  4029. } else
  4030. #endif
  4031. #ifdef CONFIG_FEATURE_SGI_LABEL
  4032. if (sgi_label) {
  4033. sgi_change_sysid(i, sys);
  4034. } else
  4035. #endif
  4036. p->sys_ind = sys;
  4037. printf (_("Changed system type of partition %d "
  4038. "to %x (%s)\n"), i + 1, sys,
  4039. partition_type(sys));
  4040. ptes[i].changed = 1;
  4041. if (is_dos_partition(origsys) ||
  4042. is_dos_partition(sys))
  4043. dos_changed = 1;
  4044. break;
  4045. }
  4046. }
  4047. }
  4048. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  4049. /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
  4050. * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
  4051. * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
  4052. * Lubkin Oct. 1991). */
  4053. static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
  4054. int spc = heads * sectors;
  4055. *c = ls / spc;
  4056. ls = ls % spc;
  4057. *h = ls / sectors;
  4058. *s = ls % sectors + 1; /* sectors count from 1 */
  4059. }
  4060. static void check_consistency(const struct partition *p, int partition) {
  4061. uint pbc, pbh, pbs; /* physical beginning c, h, s */
  4062. uint pec, peh, pes; /* physical ending c, h, s */
  4063. uint lbc, lbh, lbs; /* logical beginning c, h, s */
  4064. uint lec, leh, les; /* logical ending c, h, s */
  4065. if (!heads || !sectors || (partition >= 4))
  4066. return; /* do not check extended partitions */
  4067. /* physical beginning c, h, s */
  4068. pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
  4069. pbh = p->head;
  4070. pbs = p->sector & 0x3f;
  4071. /* physical ending c, h, s */
  4072. pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
  4073. peh = p->end_head;
  4074. pes = p->end_sector & 0x3f;
  4075. /* compute logical beginning (c, h, s) */
  4076. long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
  4077. /* compute logical ending (c, h, s) */
  4078. long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
  4079. /* Same physical / logical beginning? */
  4080. if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
  4081. printf(_("Partition %d has different physical/logical "
  4082. "beginnings (non-Linux?):\n"), partition + 1);
  4083. printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
  4084. printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
  4085. }
  4086. /* Same physical / logical ending? */
  4087. if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
  4088. printf(_("Partition %d has different physical/logical "
  4089. "endings:\n"), partition + 1);
  4090. printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
  4091. printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
  4092. }
  4093. #if 0
  4094. /* Beginning on cylinder boundary? */
  4095. if (pbh != !pbc || pbs != 1) {
  4096. printf(_("Partition %i does not start on cylinder "
  4097. "boundary:\n"), partition + 1);
  4098. printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
  4099. printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
  4100. }
  4101. #endif
  4102. /* Ending on cylinder boundary? */
  4103. if (peh != (heads - 1) || pes != sectors) {
  4104. printf(_("Partition %i does not end on cylinder boundary.\n"),
  4105. partition + 1);
  4106. #if 0
  4107. printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
  4108. printf(_("should be (%d, %d, %d)\n"),
  4109. pec, heads - 1, sectors);
  4110. #endif
  4111. }
  4112. }
  4113. static void
  4114. list_disk_geometry(void) {
  4115. long long bytes = (total_number_of_sectors << 9);
  4116. long megabytes = bytes/1000000;
  4117. if (megabytes < 10000)
  4118. printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
  4119. disk_device, megabytes, bytes);
  4120. else
  4121. printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
  4122. disk_device, megabytes/1000, (megabytes/100)%10, bytes);
  4123. printf(_("%d heads, %d sectors/track, %d cylinders"),
  4124. heads, sectors, cylinders);
  4125. if (units_per_sector == 1)
  4126. printf(_(", total %llu sectors"),
  4127. total_number_of_sectors / (sector_size/512));
  4128. printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
  4129. str_units(PLURAL),
  4130. units_per_sector, sector_size, units_per_sector * sector_size);
  4131. }
  4132. /*
  4133. * Check whether partition entries are ordered by their starting positions.
  4134. * Return 0 if OK. Return i if partition i should have been earlier.
  4135. * Two separate checks: primary and logical partitions.
  4136. */
  4137. static int
  4138. wrong_p_order(int *prev) {
  4139. const struct pte *pe;
  4140. const struct partition *p;
  4141. off_t last_p_start_pos = 0, p_start_pos;
  4142. int i, last_i = 0;
  4143. for (i = 0 ; i < partitions; i++) {
  4144. if (i == 4) {
  4145. last_i = 4;
  4146. last_p_start_pos = 0;
  4147. }
  4148. pe = &ptes[i];
  4149. if ((p = pe->part_table)->sys_ind) {
  4150. p_start_pos = get_partition_start(pe);
  4151. if (last_p_start_pos > p_start_pos) {
  4152. if (prev)
  4153. *prev = last_i;
  4154. return i;
  4155. }
  4156. last_p_start_pos = p_start_pos;
  4157. last_i = i;
  4158. }
  4159. }
  4160. return 0;
  4161. }
  4162. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  4163. /*
  4164. * Fix the chain of logicals.
  4165. * extended_offset is unchanged, the set of sectors used is unchanged
  4166. * The chain is sorted so that sectors increase, and so that
  4167. * starting sectors increase.
  4168. *
  4169. * After this it may still be that cfdisk doesnt like the table.
  4170. * (This is because cfdisk considers expanded parts, from link to
  4171. * end of partition, and these may still overlap.)
  4172. * Now
  4173. * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
  4174. * may help.
  4175. */
  4176. static void
  4177. fix_chain_of_logicals(void) {
  4178. int j, oj, ojj, sj, sjj;
  4179. struct partition *pj,*pjj,tmp;
  4180. /* Stage 1: sort sectors but leave sector of part 4 */
  4181. /* (Its sector is the global extended_offset.) */
  4182. stage1:
  4183. for (j = 5; j < partitions-1; j++) {
  4184. oj = ptes[j].offset;
  4185. ojj = ptes[j+1].offset;
  4186. if (oj > ojj) {
  4187. ptes[j].offset = ojj;
  4188. ptes[j+1].offset = oj;
  4189. pj = ptes[j].part_table;
  4190. set_start_sect(pj, get_start_sect(pj)+oj-ojj);
  4191. pjj = ptes[j+1].part_table;
  4192. set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
  4193. set_start_sect(ptes[j-1].ext_pointer,
  4194. ojj-extended_offset);
  4195. set_start_sect(ptes[j].ext_pointer,
  4196. oj-extended_offset);
  4197. goto stage1;
  4198. }
  4199. }
  4200. /* Stage 2: sort starting sectors */
  4201. stage2:
  4202. for (j = 4; j < partitions-1; j++) {
  4203. pj = ptes[j].part_table;
  4204. pjj = ptes[j+1].part_table;
  4205. sj = get_start_sect(pj);
  4206. sjj = get_start_sect(pjj);
  4207. oj = ptes[j].offset;
  4208. ojj = ptes[j+1].offset;
  4209. if (oj+sj > ojj+sjj) {
  4210. tmp = *pj;
  4211. *pj = *pjj;
  4212. *pjj = tmp;
  4213. set_start_sect(pj, ojj+sjj-oj);
  4214. set_start_sect(pjj, oj+sj-ojj);
  4215. goto stage2;
  4216. }
  4217. }
  4218. /* Probably something was changed */
  4219. for (j = 4; j < partitions; j++)
  4220. ptes[j].changed = 1;
  4221. }
  4222. static void
  4223. fix_partition_table_order(void) {
  4224. struct pte *pei, *pek;
  4225. int i,k;
  4226. if (!wrong_p_order(NULL)) {
  4227. printf(_("Nothing to do. Ordering is correct already.\n\n"));
  4228. return;
  4229. }
  4230. while ((i = wrong_p_order(&k)) != 0 && i < 4) {
  4231. /* partition i should have come earlier, move it */
  4232. /* We have to move data in the MBR */
  4233. struct partition *pi, *pk, *pe, pbuf;
  4234. pei = &ptes[i];
  4235. pek = &ptes[k];
  4236. pe = pei->ext_pointer;
  4237. pei->ext_pointer = pek->ext_pointer;
  4238. pek->ext_pointer = pe;
  4239. pi = pei->part_table;
  4240. pk = pek->part_table;
  4241. memmove(&pbuf, pi, sizeof(struct partition));
  4242. memmove(pi, pk, sizeof(struct partition));
  4243. memmove(pk, &pbuf, sizeof(struct partition));
  4244. pei->changed = pek->changed = 1;
  4245. }
  4246. if (i)
  4247. fix_chain_of_logicals();
  4248. printf("Done.\n");
  4249. }
  4250. #endif
  4251. static void
  4252. list_table(int xtra) {
  4253. const struct partition *p;
  4254. int i, w;
  4255. #ifdef CONFIG_FEATURE_SUN_LABEL
  4256. if (sun_label) {
  4257. sun_list_table(xtra);
  4258. return;
  4259. }
  4260. #endif
  4261. #ifdef CONFIG_FEATURE_SGI_LABEL
  4262. if (sgi_label) {
  4263. sgi_list_table(xtra);
  4264. return;
  4265. }
  4266. #endif
  4267. list_disk_geometry();
  4268. #ifdef CONFIG_FEATURE_OSF_LABEL
  4269. if (osf_label) {
  4270. xbsd_print_disklabel(xtra);
  4271. return;
  4272. }
  4273. #endif
  4274. /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
  4275. but if the device name ends in a digit, say /dev/foo1,
  4276. then the partition is called /dev/foo1p3. */
  4277. w = strlen(disk_device);
  4278. if (w && isdigit(disk_device[w-1]))
  4279. w++;
  4280. if (w < 5)
  4281. w = 5;
  4282. printf(_("%*s Boot Start End Blocks Id System\n"),
  4283. w+1, _("Device"));
  4284. for (i = 0; i < partitions; i++) {
  4285. const struct pte *pe = &ptes[i];
  4286. p = pe->part_table;
  4287. if (p && !is_cleared_partition(p)) {
  4288. off_t psects = get_nr_sects(p);
  4289. off_t pblocks = psects;
  4290. unsigned int podd = 0;
  4291. if (sector_size < 1024) {
  4292. pblocks /= (1024 / sector_size);
  4293. podd = psects % (1024 / sector_size);
  4294. }
  4295. if (sector_size > 1024)
  4296. pblocks *= (sector_size / 1024);
  4297. printf(
  4298. "%s %c %11llu %11llu %11llu%c %2x %s\n",
  4299. partname(disk_device, i+1, w+2),
  4300. /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
  4301. ? '*' : '?',
  4302. /* start */ (unsigned long long) cround(get_partition_start(pe)),
  4303. /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
  4304. - (psects ? 1 : 0)),
  4305. /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
  4306. /* type id */ p->sys_ind,
  4307. /* type name */ partition_type(p->sys_ind));
  4308. check_consistency(p, i);
  4309. }
  4310. }
  4311. /* Is partition table in disk order? It need not be, but... */
  4312. /* partition table entries are not checked for correct order if this
  4313. is a sgi, sun or aix labeled disk... */
  4314. if (dos_label && wrong_p_order(NULL)) {
  4315. printf(_("\nPartition table entries are not in disk order\n"));
  4316. }
  4317. }
  4318. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  4319. static void
  4320. x_list_table(int extend) {
  4321. const struct pte *pe;
  4322. const struct partition *p;
  4323. int i;
  4324. printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
  4325. disk_device, heads, sectors, cylinders);
  4326. printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
  4327. for (i = 0 ; i < partitions; i++) {
  4328. pe = &ptes[i];
  4329. p = (extend ? pe->ext_pointer : pe->part_table);
  4330. if (p != NULL) {
  4331. printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
  4332. i + 1, p->boot_ind, p->head,
  4333. sector(p->sector),
  4334. cylinder(p->sector, p->cyl), p->end_head,
  4335. sector(p->end_sector),
  4336. cylinder(p->end_sector, p->end_cyl),
  4337. get_start_sect(p), get_nr_sects(p), p->sys_ind);
  4338. if (p->sys_ind)
  4339. check_consistency(p, i);
  4340. }
  4341. }
  4342. }
  4343. #endif
  4344. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  4345. static void
  4346. fill_bounds(off_t *first, off_t *last) {
  4347. int i;
  4348. const struct pte *pe = &ptes[0];
  4349. const struct partition *p;
  4350. for (i = 0; i < partitions; pe++,i++) {
  4351. p = pe->part_table;
  4352. if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
  4353. first[i] = 0xffffffff;
  4354. last[i] = 0;
  4355. } else {
  4356. first[i] = get_partition_start(pe);
  4357. last[i] = first[i] + get_nr_sects(p) - 1;
  4358. }
  4359. }
  4360. }
  4361. static void
  4362. check(int n, uint h, uint s, uint c, off_t start) {
  4363. off_t total, real_s, real_c;
  4364. real_s = sector(s) - 1;
  4365. real_c = cylinder(s, c);
  4366. total = (real_c * sectors + real_s) * heads + h;
  4367. if (!total)
  4368. fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
  4369. if (h >= heads)
  4370. fprintf(stderr,
  4371. _("Partition %d: head %d greater than maximum %d\n"),
  4372. n, h + 1, heads);
  4373. if (real_s >= sectors)
  4374. fprintf(stderr, _("Partition %d: sector %d greater than "
  4375. "maximum %d\n"), n, s, sectors);
  4376. if (real_c >= cylinders)
  4377. fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
  4378. "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
  4379. if (cylinders <= 1024 && start != total)
  4380. fprintf(stderr,
  4381. _("Partition %d: previous sectors %llu disagrees with "
  4382. "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
  4383. }
  4384. static void
  4385. verify(void) {
  4386. int i, j;
  4387. uint total = 1;
  4388. off_t first[partitions], last[partitions];
  4389. struct partition *p;
  4390. if (warn_geometry())
  4391. return;
  4392. #ifdef CONFIG_FEATURE_SUN_LABEL
  4393. if (sun_label) {
  4394. verify_sun();
  4395. return;
  4396. }
  4397. #endif
  4398. #ifdef CONFIG_FEATURE_SGI_LABEL
  4399. if (sgi_label) {
  4400. verify_sgi(1);
  4401. return;
  4402. }
  4403. #endif
  4404. fill_bounds(first, last);
  4405. for (i = 0; i < partitions; i++) {
  4406. struct pte *pe = &ptes[i];
  4407. p = pe->part_table;
  4408. if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
  4409. check_consistency(p, i);
  4410. if (get_partition_start(pe) < first[i])
  4411. printf(_("Warning: bad start-of-data in "
  4412. "partition %d\n"), i + 1);
  4413. check(i + 1, p->end_head, p->end_sector, p->end_cyl,
  4414. last[i]);
  4415. total += last[i] + 1 - first[i];
  4416. for (j = 0; j < i; j++)
  4417. if ((first[i] >= first[j] && first[i] <= last[j])
  4418. || ((last[i] <= last[j] && last[i] >= first[j]))) {
  4419. printf(_("Warning: partition %d overlaps "
  4420. "partition %d.\n"), j + 1, i + 1);
  4421. total += first[i] >= first[j] ?
  4422. first[i] : first[j];
  4423. total -= last[i] <= last[j] ?
  4424. last[i] : last[j];
  4425. }
  4426. }
  4427. }
  4428. if (extended_offset) {
  4429. struct pte *pex = &ptes[ext_index];
  4430. off_t e_last = get_start_sect(pex->part_table) +
  4431. get_nr_sects(pex->part_table) - 1;
  4432. for (i = 4; i < partitions; i++) {
  4433. total++;
  4434. p = ptes[i].part_table;
  4435. if (!p->sys_ind) {
  4436. if (i != 4 || i + 1 < partitions)
  4437. printf(_("Warning: partition %d "
  4438. "is empty\n"), i + 1);
  4439. }
  4440. else if (first[i] < extended_offset ||
  4441. last[i] > e_last)
  4442. printf(_("Logical partition %d not entirely in "
  4443. "partition %d\n"), i + 1, ext_index + 1);
  4444. }
  4445. }
  4446. if (total > heads * sectors * cylinders)
  4447. printf(_("Total allocated sectors %d greater than the maximum "
  4448. "%d\n"), total, heads * sectors * cylinders);
  4449. else if ((total = heads * sectors * cylinders - total) != 0)
  4450. printf(_("%d unallocated sectors\n"), total);
  4451. }
  4452. static void
  4453. add_partition(int n, int sys) {
  4454. char mesg[256]; /* 48 does not suffice in Japanese */
  4455. int i, readed = 0;
  4456. struct partition *p = ptes[n].part_table;
  4457. struct partition *q = ptes[ext_index].part_table;
  4458. long long llimit;
  4459. off_t start, stop = 0, limit, temp,
  4460. first[partitions], last[partitions];
  4461. if (p && p->sys_ind) {
  4462. printf(_("Partition %d is already defined. Delete "
  4463. "it before re-adding it.\n"), n + 1);
  4464. return;
  4465. }
  4466. fill_bounds(first, last);
  4467. if (n < 4) {
  4468. start = sector_offset;
  4469. if (display_in_cyl_units || !total_number_of_sectors)
  4470. llimit = heads * sectors * cylinders - 1;
  4471. else
  4472. llimit = total_number_of_sectors - 1;
  4473. limit = llimit;
  4474. if (limit != llimit)
  4475. limit = 0x7fffffff;
  4476. if (extended_offset) {
  4477. first[ext_index] = extended_offset;
  4478. last[ext_index] = get_start_sect(q) +
  4479. get_nr_sects(q) - 1;
  4480. }
  4481. } else {
  4482. start = extended_offset + sector_offset;
  4483. limit = get_start_sect(q) + get_nr_sects(q) - 1;
  4484. }
  4485. if (display_in_cyl_units)
  4486. for (i = 0; i < partitions; i++)
  4487. first[i] = (cround(first[i]) - 1) * units_per_sector;
  4488. snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
  4489. do {
  4490. temp = start;
  4491. for (i = 0; i < partitions; i++) {
  4492. int lastplusoff;
  4493. if (start == ptes[i].offset)
  4494. start += sector_offset;
  4495. lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
  4496. if (start >= first[i] && start <= lastplusoff)
  4497. start = lastplusoff + 1;
  4498. }
  4499. if (start > limit)
  4500. break;
  4501. if (start >= temp+units_per_sector && readed) {
  4502. printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
  4503. temp = start;
  4504. readed = 0;
  4505. }
  4506. if (!readed && start == temp) {
  4507. off_t saved_start;
  4508. saved_start = start;
  4509. start = read_int(cround(saved_start), cround(saved_start), cround(limit),
  4510. 0, mesg);
  4511. if (display_in_cyl_units) {
  4512. start = (start - 1) * units_per_sector;
  4513. if (start < saved_start) start = saved_start;
  4514. }
  4515. readed = 1;
  4516. }
  4517. } while (start != temp || !readed);
  4518. if (n > 4) { /* NOT for fifth partition */
  4519. struct pte *pe = &ptes[n];
  4520. pe->offset = start - sector_offset;
  4521. if (pe->offset == extended_offset) { /* must be corrected */
  4522. pe->offset++;
  4523. if (sector_offset == 1)
  4524. start++;
  4525. }
  4526. }
  4527. for (i = 0; i < partitions; i++) {
  4528. struct pte *pe = &ptes[i];
  4529. if (start < pe->offset && limit >= pe->offset)
  4530. limit = pe->offset - 1;
  4531. if (start < first[i] && limit >= first[i])
  4532. limit = first[i] - 1;
  4533. }
  4534. if (start > limit) {
  4535. printf(_("No free sectors available\n"));
  4536. if (n > 4)
  4537. partitions--;
  4538. return;
  4539. }
  4540. if (cround(start) == cround(limit)) {
  4541. stop = limit;
  4542. } else {
  4543. snprintf(mesg, sizeof(mesg),
  4544. _("Last %s or +size or +sizeM or +sizeK"),
  4545. str_units(SINGULAR));
  4546. stop = read_int(cround(start), cround(limit), cround(limit),
  4547. cround(start), mesg);
  4548. if (display_in_cyl_units) {
  4549. stop = stop * units_per_sector - 1;
  4550. if (stop >limit)
  4551. stop = limit;
  4552. }
  4553. }
  4554. set_partition(n, 0, start, stop, sys);
  4555. if (n > 4)
  4556. set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
  4557. if (IS_EXTENDED (sys)) {
  4558. struct pte *pe4 = &ptes[4];
  4559. struct pte *pen = &ptes[n];
  4560. ext_index = n;
  4561. pen->ext_pointer = p;
  4562. pe4->offset = extended_offset = start;
  4563. pe4->sectorbuffer = xcalloc(1, sector_size);
  4564. pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
  4565. pe4->ext_pointer = pe4->part_table + 1;
  4566. pe4->changed = 1;
  4567. partitions = 5;
  4568. }
  4569. }
  4570. static void
  4571. add_logical(void) {
  4572. if (partitions > 5 || ptes[4].part_table->sys_ind) {
  4573. struct pte *pe = &ptes[partitions];
  4574. pe->sectorbuffer = xcalloc(1, sector_size);
  4575. pe->part_table = pt_offset(pe->sectorbuffer, 0);
  4576. pe->ext_pointer = pe->part_table + 1;
  4577. pe->offset = 0;
  4578. pe->changed = 1;
  4579. partitions++;
  4580. }
  4581. add_partition(partitions - 1, LINUX_NATIVE);
  4582. }
  4583. static void
  4584. new_partition(void) {
  4585. int i, free_primary = 0;
  4586. if (warn_geometry())
  4587. return;
  4588. #ifdef CONFIG_FEATURE_SUN_LABEL
  4589. if (sun_label) {
  4590. add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
  4591. return;
  4592. }
  4593. #endif
  4594. #ifdef CONFIG_FEATURE_SGI_LABEL
  4595. if (sgi_label) {
  4596. sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
  4597. return;
  4598. }
  4599. #endif
  4600. #ifdef CONFIG_FEATURE_AIX_LABEL
  4601. if (aix_label) {
  4602. printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
  4603. "\n\tIf you want to add DOS-type partitions, create"
  4604. "\n\ta new empty DOS partition table first. (Use o.)"
  4605. "\n\tWARNING: "
  4606. "This will destroy the present disk contents.\n"));
  4607. return;
  4608. }
  4609. #endif
  4610. for (i = 0; i < 4; i++)
  4611. free_primary += !ptes[i].part_table->sys_ind;
  4612. if (!free_primary && partitions >= MAXIMUM_PARTS) {
  4613. printf(_("The maximum number of partitions has been created\n"));
  4614. return;
  4615. }
  4616. if (!free_primary) {
  4617. if (extended_offset)
  4618. add_logical();
  4619. else
  4620. printf(_("You must delete some partition and add "
  4621. "an extended partition first\n"));
  4622. } else {
  4623. char c, line[LINE_LENGTH];
  4624. snprintf(line, sizeof(line), "%s\n %s\n p primary "
  4625. "partition (1-4)\n",
  4626. "Command action", (extended_offset ?
  4627. "l logical (5 or over)" : "e extended"));
  4628. while (1) {
  4629. if ((c = read_char(line)) == 'p' || c == 'P') {
  4630. i = get_nonexisting_partition(0, 4);
  4631. if (i >= 0)
  4632. add_partition(i, LINUX_NATIVE);
  4633. return;
  4634. }
  4635. else if (c == 'l' && extended_offset) {
  4636. add_logical();
  4637. return;
  4638. }
  4639. else if (c == 'e' && !extended_offset) {
  4640. i = get_nonexisting_partition(0, 4);
  4641. if (i >= 0)
  4642. add_partition(i, EXTENDED);
  4643. return;
  4644. }
  4645. else
  4646. printf(_("Invalid partition number "
  4647. "for type `%c'\n"), c);
  4648. }
  4649. }
  4650. }
  4651. static void
  4652. write_table(void) {
  4653. int i;
  4654. if (dos_label) {
  4655. for (i=0; i<3; i++)
  4656. if (ptes[i].changed)
  4657. ptes[3].changed = 1;
  4658. for (i = 3; i < partitions; i++) {
  4659. struct pte *pe = &ptes[i];
  4660. if (pe->changed) {
  4661. write_part_table_flag(pe->sectorbuffer);
  4662. write_sector(pe->offset, pe->sectorbuffer);
  4663. }
  4664. }
  4665. }
  4666. #ifdef CONFIG_FEATURE_SGI_LABEL
  4667. else if (sgi_label) {
  4668. /* no test on change? the printf below might be mistaken */
  4669. sgi_write_table();
  4670. }
  4671. #endif
  4672. #ifdef CONFIG_FEATURE_SUN_LABEL
  4673. else if (sun_label) {
  4674. int needw = 0;
  4675. for (i=0; i<8; i++)
  4676. if (ptes[i].changed)
  4677. needw = 1;
  4678. if (needw)
  4679. sun_write_table();
  4680. }
  4681. #endif
  4682. printf(_("The partition table has been altered!\n\n"));
  4683. reread_partition_table(1);
  4684. }
  4685. void
  4686. reread_partition_table(int leave) {
  4687. int error = 0;
  4688. int i;
  4689. printf(_("Calling ioctl() to re-read partition table.\n"));
  4690. sync();
  4691. sleep(2);
  4692. if ((i = ioctl(fd, BLKRRPART)) != 0) {
  4693. error = errno;
  4694. } else {
  4695. /* some kernel versions (1.2.x) seem to have trouble
  4696. rereading the partition table, but if asked to do it
  4697. twice, the second time works. - biro@yggdrasil.com */
  4698. sync();
  4699. sleep(2);
  4700. if ((i = ioctl(fd, BLKRRPART)) != 0)
  4701. error = errno;
  4702. }
  4703. if (i) {
  4704. printf(_("\nWARNING: Re-reading the partition table "
  4705. "failed with error %d: %s.\n"
  4706. "The kernel still uses the old table.\n"
  4707. "The new table will be used "
  4708. "at the next reboot.\n"),
  4709. error, strerror(error));
  4710. }
  4711. if (dos_changed)
  4712. printf(
  4713. _("\nWARNING: If you have created or modified any DOS 6.x\n"
  4714. "partitions, please see the fdisk manual page for additional\n"
  4715. "information.\n"));
  4716. if (leave) {
  4717. close(fd);
  4718. printf(_("Syncing disks.\n"));
  4719. sync();
  4720. sleep(4); /* for sync() */
  4721. exit(!!i);
  4722. }
  4723. }
  4724. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  4725. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  4726. #define MAX_PER_LINE 16
  4727. static void
  4728. print_buffer(char pbuffer[]) {
  4729. int i,
  4730. l;
  4731. for (i = 0, l = 0; i < sector_size; i++, l++) {
  4732. if (l == 0)
  4733. printf("0x%03X:", i);
  4734. printf(" %02X", (unsigned char) pbuffer[i]);
  4735. if (l == MAX_PER_LINE - 1) {
  4736. printf("\n");
  4737. l = -1;
  4738. }
  4739. }
  4740. if (l > 0)
  4741. printf("\n");
  4742. printf("\n");
  4743. }
  4744. static void
  4745. print_raw(void) {
  4746. int i;
  4747. printf(_("Device: %s\n"), disk_device);
  4748. #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
  4749. if (sun_label || sgi_label)
  4750. print_buffer(MBRbuffer);
  4751. else
  4752. #endif
  4753. for (i = 3; i < partitions; i++)
  4754. print_buffer(ptes[i].sectorbuffer);
  4755. }
  4756. static void
  4757. move_begin(int i) {
  4758. struct pte *pe = &ptes[i];
  4759. struct partition *p = pe->part_table;
  4760. off_t new, first;
  4761. if (warn_geometry())
  4762. return;
  4763. if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
  4764. printf(_("Partition %d has no data area\n"), i + 1);
  4765. return;
  4766. }
  4767. first = get_partition_start(pe);
  4768. new = read_int(first, first, first + get_nr_sects(p) - 1, first,
  4769. _("New beginning of data")) - pe->offset;
  4770. if (new != get_nr_sects(p)) {
  4771. first = get_nr_sects(p) + get_start_sect(p) - new;
  4772. set_nr_sects(p, first);
  4773. set_start_sect(p, new);
  4774. pe->changed = 1;
  4775. }
  4776. }
  4777. static void
  4778. xselect(void) {
  4779. char c;
  4780. while(1) {
  4781. putchar('\n');
  4782. c = tolower(read_char(_("Expert command (m for help): ")));
  4783. switch (c) {
  4784. case 'a':
  4785. #ifdef CONFIG_FEATURE_SUN_LABEL
  4786. if (sun_label)
  4787. sun_set_alt_cyl();
  4788. #endif
  4789. break;
  4790. case 'b':
  4791. if (dos_label)
  4792. move_begin(get_partition(0, partitions));
  4793. break;
  4794. case 'c':
  4795. user_cylinders = cylinders =
  4796. read_int(1, cylinders, 1048576, 0,
  4797. _("Number of cylinders"));
  4798. #ifdef CONFIG_FEATURE_SUN_LABEL
  4799. if (sun_label)
  4800. sun_set_ncyl(cylinders);
  4801. #endif
  4802. if (dos_label)
  4803. warn_cylinders();
  4804. break;
  4805. case 'd':
  4806. print_raw();
  4807. break;
  4808. case 'e':
  4809. #ifdef CONFIG_FEATURE_SGI_LABEL
  4810. if (sgi_label)
  4811. sgi_set_xcyl();
  4812. else
  4813. #endif
  4814. #ifdef CONFIG_FEATURE_SUN_LABEL
  4815. if (sun_label)
  4816. sun_set_xcyl();
  4817. else
  4818. #endif
  4819. if (dos_label)
  4820. x_list_table(1);
  4821. break;
  4822. case 'f':
  4823. if (dos_label)
  4824. fix_partition_table_order();
  4825. break;
  4826. case 'g':
  4827. #ifdef CONFIG_FEATURE_SGI_LABEL
  4828. create_sgilabel();
  4829. #endif
  4830. break;
  4831. case 'h':
  4832. user_heads = heads = read_int(1, heads, 256, 0,
  4833. _("Number of heads"));
  4834. update_units();
  4835. break;
  4836. case 'i':
  4837. #ifdef CONFIG_FEATURE_SUN_LABEL
  4838. if (sun_label)
  4839. sun_set_ilfact();
  4840. #endif
  4841. break;
  4842. case 'o':
  4843. #ifdef CONFIG_FEATURE_SUN_LABEL
  4844. if (sun_label)
  4845. sun_set_rspeed();
  4846. #endif
  4847. break;
  4848. case 'p':
  4849. #ifdef CONFIG_FEATURE_SUN_LABEL
  4850. if (sun_label)
  4851. list_table(1);
  4852. else
  4853. #endif
  4854. x_list_table(0);
  4855. break;
  4856. case 'q':
  4857. close(fd);
  4858. printf("\n");
  4859. exit(0);
  4860. case 'r':
  4861. return;
  4862. case 's':
  4863. user_sectors = sectors = read_int(1, sectors, 63, 0,
  4864. _("Number of sectors"));
  4865. if (dos_compatible_flag) {
  4866. sector_offset = sectors;
  4867. fprintf(stderr, _("Warning: setting "
  4868. "sector offset for DOS "
  4869. "compatiblity\n"));
  4870. }
  4871. update_units();
  4872. break;
  4873. case 'v':
  4874. verify();
  4875. break;
  4876. case 'w':
  4877. write_table(); /* does not return */
  4878. break;
  4879. case 'y':
  4880. #ifdef CONFIG_FEATURE_SUN_LABEL
  4881. if (sun_label)
  4882. sun_set_pcylcount();
  4883. #endif
  4884. break;
  4885. default:
  4886. xmenu();
  4887. }
  4888. }
  4889. }
  4890. #endif /* ADVANCED mode */
  4891. static int
  4892. is_ide_cdrom_or_tape(const char *device) {
  4893. FILE *procf;
  4894. char buf[100];
  4895. struct stat statbuf;
  4896. int is_ide = 0;
  4897. /* No device was given explicitly, and we are trying some
  4898. likely things. But opening /dev/hdc may produce errors like
  4899. "hdc: tray open or drive not ready"
  4900. if it happens to be a CD-ROM drive. It even happens that
  4901. the process hangs on the attempt to read a music CD.
  4902. So try to be careful. This only works since 2.1.73. */
  4903. if (strncmp("/dev/hd", device, 7))
  4904. return 0;
  4905. snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
  4906. procf = fopen(buf, "r");
  4907. if (procf != NULL && fgets(buf, sizeof(buf), procf))
  4908. is_ide = (!strncmp(buf, "cdrom", 5) ||
  4909. !strncmp(buf, "tape", 4));
  4910. else
  4911. /* Now when this proc file does not exist, skip the
  4912. device when it is read-only. */
  4913. if (stat(device, &statbuf) == 0)
  4914. is_ide = ((statbuf.st_mode & 0222) == 0);
  4915. if (procf)
  4916. fclose(procf);
  4917. return is_ide;
  4918. }
  4919. static void
  4920. try(const char *device, int user_specified) {
  4921. int gb;
  4922. disk_device = device;
  4923. if (setjmp(listingbuf))
  4924. return;
  4925. if (!user_specified)
  4926. if (is_ide_cdrom_or_tape(device))
  4927. return;
  4928. if ((fd = open(disk_device, type_open)) >= 0) {
  4929. gb = get_boot(try_only);
  4930. if (gb > 0) { /* I/O error */
  4931. close(fd);
  4932. } else if (gb < 0) { /* no DOS signature */
  4933. list_disk_geometry();
  4934. if (aix_label)
  4935. return;
  4936. #ifdef CONFIG_FEATURE_OSF_LABEL
  4937. if (btrydev(device) < 0)
  4938. #endif
  4939. fprintf(stderr,
  4940. _("Disk %s doesn't contain a valid "
  4941. "partition table\n"), device);
  4942. close(fd);
  4943. } else {
  4944. close(fd);
  4945. list_table(0);
  4946. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  4947. if (!sun_label && partitions > 4)
  4948. delete_partition(ext_index);
  4949. #endif
  4950. }
  4951. } else {
  4952. /* Ignore other errors, since we try IDE
  4953. and SCSI hard disks which may not be
  4954. installed on the system. */
  4955. if (errno == EACCES) {
  4956. fprintf(stderr, _("Cannot open %s\n"), device);
  4957. return;
  4958. }
  4959. }
  4960. }
  4961. /* for fdisk -l: try all things in /proc/partitions
  4962. that look like a partition name (do not end in a digit) */
  4963. static void
  4964. tryprocpt(void) {
  4965. FILE *procpt;
  4966. char line[100], ptname[100], devname[120], *s;
  4967. int ma, mi, sz;
  4968. procpt = bb_wfopen(PROC_PARTITIONS, "r");
  4969. while (fgets(line, sizeof(line), procpt)) {
  4970. if (sscanf (line, " %d %d %d %[^\n ]",
  4971. &ma, &mi, &sz, ptname) != 4)
  4972. continue;
  4973. for (s = ptname; *s; s++);
  4974. if (isdigit(s[-1]))
  4975. continue;
  4976. sprintf(devname, "/dev/%s", ptname);
  4977. try(devname, 0);
  4978. }
  4979. #ifdef CONFIG_FEATURE_CLEAN_UP
  4980. fclose(procpt);
  4981. #endif
  4982. }
  4983. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  4984. static void
  4985. unknown_command(int c) {
  4986. printf(_("%c: unknown command\n"), c);
  4987. }
  4988. #endif
  4989. int fdisk_main(int argc, char **argv) {
  4990. int c;
  4991. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  4992. int optl = 0;
  4993. #endif
  4994. #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
  4995. int opts = 0;
  4996. #endif
  4997. /*
  4998. * Calls:
  4999. * fdisk -v
  5000. * fdisk -l [-b sectorsize] [-u] device ...
  5001. * fdisk -s [partition] ...
  5002. * fdisk [-b sectorsize] [-u] device
  5003. *
  5004. * Options -C, -H, -S set the geometry.
  5005. *
  5006. */
  5007. while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
  5008. #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
  5009. "s"
  5010. #endif
  5011. )) != -1) {
  5012. switch (c) {
  5013. case 'b':
  5014. /* Ugly: this sector size is really per device,
  5015. so cannot be combined with multiple disks,
  5016. and te same goes for the C/H/S options.
  5017. */
  5018. sector_size = atoi(optarg);
  5019. if (sector_size != 512 && sector_size != 1024 &&
  5020. sector_size != 2048)
  5021. bb_show_usage();
  5022. sector_offset = 2;
  5023. user_set_sector_size = 1;
  5024. break;
  5025. case 'C':
  5026. user_cylinders = atoi(optarg);
  5027. break;
  5028. case 'H':
  5029. user_heads = atoi(optarg);
  5030. if (user_heads <= 0 || user_heads >= 256)
  5031. user_heads = 0;
  5032. break;
  5033. case 'S':
  5034. user_sectors = atoi(optarg);
  5035. if (user_sectors <= 0 || user_sectors >= 64)
  5036. user_sectors = 0;
  5037. break;
  5038. case 'l':
  5039. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  5040. optl = 1;
  5041. #endif
  5042. break;
  5043. #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
  5044. case 's':
  5045. opts = 1;
  5046. break;
  5047. #endif
  5048. case 'u':
  5049. display_in_cyl_units = 0;
  5050. break;
  5051. case 'V':
  5052. case 'v':
  5053. printf("fdisk v" UTIL_LINUX_VERSION "\n");
  5054. return 0;
  5055. default:
  5056. bb_show_usage();
  5057. }
  5058. }
  5059. #if 0
  5060. printf(_("This kernel finds the sector size itself - "
  5061. "-b option ignored\n"));
  5062. #else
  5063. if (user_set_sector_size && argc-optind != 1)
  5064. printf(_("Warning: the -b (set sector size) option should"
  5065. " be used with one specified device\n"));
  5066. #endif
  5067. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  5068. if (optl) {
  5069. nowarn = 1;
  5070. #endif
  5071. type_open = O_RDONLY;
  5072. if (argc > optind) {
  5073. int k;
  5074. #if __GNUC__
  5075. /* avoid gcc warning:
  5076. variable `k' might be clobbered by `longjmp' */
  5077. (void)&k;
  5078. #endif
  5079. listing = 1;
  5080. for (k=optind; k<argc; k++)
  5081. try(argv[k], 1);
  5082. } else {
  5083. /* we no longer have default device names */
  5084. /* but, we can use /proc/partitions instead */
  5085. tryprocpt();
  5086. }
  5087. return 0;
  5088. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  5089. }
  5090. #endif
  5091. #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
  5092. if (opts) {
  5093. long size;
  5094. int j;
  5095. nowarn = 1;
  5096. type_open = O_RDONLY;
  5097. opts = argc - optind;
  5098. if (opts <= 0)
  5099. bb_show_usage();
  5100. for (j = optind; j < argc; j++) {
  5101. disk_device = argv[j];
  5102. if ((fd = open(disk_device, type_open)) < 0)
  5103. fdisk_fatal(unable_to_open);
  5104. if (ioctl(fd, BLKGETSIZE, &size))
  5105. fdisk_fatal(ioctl_error);
  5106. close(fd);
  5107. if (opts == 1)
  5108. printf("%ld\n", size/2);
  5109. else
  5110. printf("%s: %ld\n", argv[j], size/2);
  5111. }
  5112. return 0;
  5113. }
  5114. #endif
  5115. #ifdef CONFIG_FEATURE_FDISK_WRITABLE
  5116. if (argc-optind == 1)
  5117. disk_device = argv[optind];
  5118. else
  5119. bb_show_usage();
  5120. get_boot(fdisk);
  5121. #ifdef CONFIG_FEATURE_OSF_LABEL
  5122. if (osf_label) {
  5123. /* OSF label, and no DOS label */
  5124. printf(_("Detected an OSF/1 disklabel on %s, entering "
  5125. "disklabel mode.\n"),
  5126. disk_device);
  5127. bselect();
  5128. osf_label = 0;
  5129. /* If we return we may want to make an empty DOS label? */
  5130. }
  5131. #endif
  5132. while (1) {
  5133. putchar('\n');
  5134. c = tolower(read_char(_("Command (m for help): ")));
  5135. switch (c) {
  5136. case 'a':
  5137. if (dos_label)
  5138. toggle_active(get_partition(1, partitions));
  5139. #ifdef CONFIG_FEATURE_SUN_LABEL
  5140. else if (sun_label)
  5141. toggle_sunflags(get_partition(1, partitions),
  5142. 0x01);
  5143. #endif
  5144. #ifdef CONFIG_FEATURE_SGI_LABEL
  5145. else if (sgi_label)
  5146. sgi_set_bootpartition(
  5147. get_partition(1, partitions));
  5148. #endif
  5149. else
  5150. unknown_command(c);
  5151. break;
  5152. case 'b':
  5153. #ifdef CONFIG_FEATURE_SGI_LABEL
  5154. if (sgi_label) {
  5155. printf(_("\nThe current boot file is: %s\n"),
  5156. sgi_get_bootfile());
  5157. if (read_chars(_("Please enter the name of the "
  5158. "new boot file: ")) == '\n')
  5159. printf(_("Boot file unchanged\n"));
  5160. else
  5161. sgi_set_bootfile(line_ptr);
  5162. } else
  5163. #endif
  5164. #ifdef CONFIG_FEATURE_OSF_LABEL
  5165. bselect();
  5166. #endif
  5167. break;
  5168. case 'c':
  5169. if (dos_label)
  5170. toggle_dos_compatibility_flag();
  5171. #ifdef CONFIG_FEATURE_SUN_LABEL
  5172. else if (sun_label)
  5173. toggle_sunflags(get_partition(1, partitions),
  5174. 0x10);
  5175. #endif
  5176. #ifdef CONFIG_FEATURE_SGI_LABEL
  5177. else if (sgi_label)
  5178. sgi_set_swappartition(
  5179. get_partition(1, partitions));
  5180. #endif
  5181. else
  5182. unknown_command(c);
  5183. break;
  5184. case 'd':
  5185. {
  5186. int j;
  5187. #ifdef CONFIG_FEATURE_SGI_LABEL
  5188. /* If sgi_label then don't use get_existing_partition,
  5189. let the user select a partition, since
  5190. get_existing_partition() only works for Linux-like
  5191. partition tables */
  5192. if (!sgi_label) {
  5193. j = get_existing_partition(1, partitions);
  5194. } else {
  5195. j = get_partition(1, partitions);
  5196. }
  5197. #else
  5198. j = get_existing_partition(1, partitions);
  5199. #endif
  5200. if (j >= 0)
  5201. delete_partition(j);
  5202. }
  5203. break;
  5204. case 'i':
  5205. #ifdef CONFIG_FEATURE_SGI_LABEL
  5206. if (sgi_label)
  5207. create_sgiinfo();
  5208. else
  5209. #endif
  5210. unknown_command(c);
  5211. case 'l':
  5212. list_types(get_sys_types());
  5213. break;
  5214. case 'm':
  5215. menu();
  5216. break;
  5217. case 'n':
  5218. new_partition();
  5219. break;
  5220. case 'o':
  5221. create_doslabel();
  5222. break;
  5223. case 'p':
  5224. list_table(0);
  5225. break;
  5226. case 'q':
  5227. close(fd);
  5228. printf("\n");
  5229. return 0;
  5230. case 's':
  5231. #ifdef CONFIG_FEATURE_SUN_LABEL
  5232. create_sunlabel();
  5233. #endif
  5234. break;
  5235. case 't':
  5236. change_sysid();
  5237. break;
  5238. case 'u':
  5239. change_units();
  5240. break;
  5241. case 'v':
  5242. verify();
  5243. break;
  5244. case 'w':
  5245. write_table(); /* does not return */
  5246. break;
  5247. #ifdef CONFIG_FEATURE_FDISK_ADVANCED
  5248. case 'x':
  5249. #ifdef CONFIG_FEATURE_SGI_LABEL
  5250. if (sgi_label) {
  5251. fprintf(stderr,
  5252. _("\n\tSorry, no experts menu for SGI "
  5253. "partition tables available.\n\n"));
  5254. } else
  5255. #endif
  5256. xselect();
  5257. break;
  5258. #endif
  5259. default:
  5260. unknown_command(c);
  5261. menu();
  5262. }
  5263. }
  5264. return 0;
  5265. #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
  5266. }